Plantilla CRISP-DM: "Climas de Australia"

Integrantes:

  • Alejandro Ferrera
  • Nicolas Dávila
  • Diego Gieminiani
Columna Descripción
Fecha Fecha de la observación
Ubicación Ubicación de la estación meteorológica
MinTemp Temperatura mínima en grados Celsius
MaxTemp Temperatura máxima en grados Celsius
Lluvia Cantidad de lluvia registrada ese día en mm.
Evaporación Evaporación (mm) en 24 horas
Sol Número de horas de sol brillante en el día
DirRafaga Dirección de la ráfaga de viento más fuerte en 24 horas.
VelRafaga Velocidad (km/hr) de la ráfaga de viento más fuerte en 24 horas.
Dir9am Dirección del viento a las 9am
Dir3pm Dirección del viento a las 3pm
Vel9am Velocidad (km/hr) del viento a las 9am
Vel3pm Velocidad (km/hr) del viento a las 3pm
Hum9am Porcentaje de humedad a las 9am
Hum3pm Porcentaje de humedad a las 3pm
Pres9am Presión atmosférica (hpa) a nivel del mar a las 9am
Pre3pm Presión atmosférica (hpa) a nivel del mar a las 3pm
Nub9am Fracción del cielo cubierto por nubes a las 9am. Se mide en "octavos", de manera que un valor 0 indica cielo totalmente despejado y 8, cielo totalmente cubierto.
Nub3pm Fracción del cielo cubierto por nubes a las 3pm. Se mide en "octavos", de manera que un valor 0 indica cielo totalmente despejado y 8, cielo totalmente cubierto.
Temp9am Temperatura en grados Celsius a las 9am
Temp3pm Temperatura en grados Celsius a las 3pm
Lluvia Hoy Variable indicadora que toma el valor 1 si la precipitación es en mm. en las últimas 24 hrs. excede 1 mm. y 0 si no.
RISK_MM La cantidad de lluvia. Una especie de medida del "riesgo".
Lluvia Man Variable indicadora que toma el valor 1 si al día siguiente llovió y 0 si no.

Fase 1: Business Understanding¶

Contexto del caso¶

Se dispone de un set de datos de observaciones meteorológicas diarias de múltiples ubicaciones en Australia, obtenidas de la Oficina de Meteorología de la Commonwealth de Australia y procesadas para crear este conjunto de datos de muestra, los datos se han procesado para proporcionar una variable objetivo RainTomorrow(si hay lluvia al día siguiente - No / Sí) y una variable de riesgo RISK_MM(cuánta lluvia registrada en milímetros), esta información se ha dejado disponible para que usted la explore y busque información que sea relevante para demostrar su aprendizaje de Minería de datos.

Para poder dar el mejor apoyo en la toma de decisiones de "Climas de Australia" nos encontramos con desafíos como:

  • Identificar patrones y relaciones en los datos de las caracteristicas del clima para entender mejor su comportamiento.
  • Desarrollar modelos de machine learning que permitan predecir comportamientos clave del clima y entender como predecir las variables objetivo.
  • Evaluar la importancia de las diferentes variables en la predicción de los comportamientos de los clientes.

Carga de dataset y dependencias¶

In [ ]:
! pip install imblearn
Requirement already satisfied: imblearn in c:\python311\lib\site-packages (0.0)
Requirement already satisfied: imbalanced-learn in c:\python311\lib\site-packages (from imblearn) (0.12.2)
Requirement already satisfied: numpy>=1.17.3 in c:\python311\lib\site-packages (from imbalanced-learn->imblearn) (1.24.3)
Requirement already satisfied: scipy>=1.5.0 in c:\python311\lib\site-packages (from imbalanced-learn->imblearn) (1.10.1)
Requirement already satisfied: scikit-learn>=1.0.2 in c:\python311\lib\site-packages (from imbalanced-learn->imblearn) (1.2.2)
Requirement already satisfied: joblib>=1.1.1 in c:\python311\lib\site-packages (from imbalanced-learn->imblearn) (1.2.0)
Requirement already satisfied: threadpoolctl>=2.0.0 in c:\python311\lib\site-packages (from imbalanced-learn->imblearn) (3.1.0)
[notice] A new release of pip available: 22.3 -> 24.1
[notice] To update, run: python.exe -m pip install --upgrade pip
In [ ]:
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
from sklearn.impute import SimpleImputer
from sklearn.impute import KNNImputer
from sklearn.preprocessing import OneHotEncoder
from imblearn.over_sampling import SMOTE
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score
import pandas as pd
In [ ]:
#Carga de dataset

df = pd.read_csv('temperatura.csv', sep=',', low_memory=False)
df.head()
Out[ ]:
Date Location MinTemp MaxTemp Rainfall Evaporation Sunshine WindGustDir WindGustSpeed WindDir9am ... Humidity3pm Pressure9am Pressure3pm Cloud9am Cloud3pm Temp9am Temp3pm RainToday RISK_MM RainTomorrow
0 2008-12-01 Albury 13.4 22.9 0.6 NaN NaN W 44.0 W ... 22.0 1007.7 1007.1 8.0 NaN 16.9 21.8 No 0.0 No
1 2008-12-02 Albury 7.4 25.1 0.0 NaN NaN WNW 44.0 NNW ... 25.0 1010.6 1007.8 NaN NaN 17.2 24.3 No 0.0 No
2 2008-12-03 Albury 12.9 25.7 0.0 NaN NaN WSW 46.0 W ... 30.0 1007.6 1008.7 NaN 2.0 21.0 23.2 No 0.0 No
3 2008-12-04 Albury 9.2 28.0 0.0 NaN NaN NE 24.0 SE ... 16.0 1017.6 1012.8 NaN NaN 18.1 26.5 No 1.0 No
4 2008-12-05 Albury 17.5 32.3 1.0 NaN NaN W 41.0 ENE ... 33.0 1010.8 1006.0 7.0 8.0 17.8 29.7 No 0.2 No

5 rows × 24 columns

In [ ]:
df.info(max_cols=30)
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 142193 entries, 0 to 142192
Data columns (total 24 columns):
 #   Column         Non-Null Count   Dtype  
---  ------         --------------   -----  
 0   Date           142193 non-null  object 
 1   Location       142193 non-null  object 
 2   MinTemp        141556 non-null  float64
 3   MaxTemp        141871 non-null  float64
 4   Rainfall       140787 non-null  float64
 5   Evaporation    81350 non-null   float64
 6   Sunshine       74377 non-null   float64
 7   WindGustDir    132863 non-null  object 
 8   WindGustSpeed  132923 non-null  float64
 9   WindDir9am     132180 non-null  object 
 10  WindDir3pm     138415 non-null  object 
 11  WindSpeed9am   140845 non-null  float64
 12  WindSpeed3pm   139563 non-null  float64
 13  Humidity9am    140419 non-null  float64
 14  Humidity3pm    138583 non-null  float64
 15  Pressure9am    128179 non-null  float64
 16  Pressure3pm    128212 non-null  float64
 17  Cloud9am       88536 non-null   float64
 18  Cloud3pm       85099 non-null   float64
 19  Temp9am        141289 non-null  float64
 20  Temp3pm        139467 non-null  float64
 21  RainToday      140787 non-null  object 
 22  RISK_MM        142193 non-null  float64
 23  RainTomorrow   142193 non-null  object 
dtypes: float64(17), object(7)
memory usage: 26.0+ MB

Fase 2: Data Understanding¶

Análisis estadístico¶

In [ ]:
df.describe().T
Out[ ]:
count mean std min 25% 50% 75% max
MinTemp 141556.0 12.186400 6.403283 -8.5 7.6 12.0 16.8 33.9
MaxTemp 141871.0 23.226784 7.117618 -4.8 17.9 22.6 28.2 48.1
Rainfall 140787.0 2.349974 8.465173 0.0 0.0 0.0 0.8 371.0
Evaporation 81350.0 5.469824 4.188537 0.0 2.6 4.8 7.4 145.0
Sunshine 74377.0 7.624853 3.781525 0.0 4.9 8.5 10.6 14.5
WindGustSpeed 132923.0 39.984292 13.588801 6.0 31.0 39.0 48.0 135.0
WindSpeed9am 140845.0 14.001988 8.893337 0.0 7.0 13.0 19.0 130.0
WindSpeed3pm 139563.0 18.637576 8.803345 0.0 13.0 19.0 24.0 87.0
Humidity9am 140419.0 68.843810 19.051293 0.0 57.0 70.0 83.0 100.0
Humidity3pm 138583.0 51.482606 20.797772 0.0 37.0 52.0 66.0 100.0
Pressure9am 128179.0 1017.653758 7.105476 980.5 1012.9 1017.6 1022.4 1041.0
Pressure3pm 128212.0 1015.258204 7.036677 977.1 1010.4 1015.2 1020.0 1039.6
Cloud9am 88536.0 4.437189 2.887016 0.0 1.0 5.0 7.0 9.0
Cloud3pm 85099.0 4.503167 2.720633 0.0 2.0 5.0 7.0 9.0
Temp9am 141289.0 16.987509 6.492838 -7.2 12.3 16.7 21.6 40.2
Temp3pm 139467.0 21.687235 6.937594 -5.4 16.6 21.1 26.4 46.7
RISK_MM 142193.0 2.360682 8.477969 0.0 0.0 0.0 0.8 371.0

Tipos de datos¶

1. Análisis de los tipos de datos¶

In [ ]:
data_types_counts = df.dtypes.value_counts()

plt.figure(figsize=(4, 5))
ax = data_types_counts.plot(kind='bar', rot=0, color='purple')

for p in ax.patches:
    ax.annotate(str(p.get_height()), (p.get_x() + p.get_width() / 2., p.get_height()),
                ha='center', va='center', xytext=(0, 5), textcoords='offset points')

plt.xlabel('Tipo de Dato')
plt.ylabel('Cantidad')
plt.title('Cantidad de cada Tipo de Dato en el DataFrame')
plt.show()
No description has been provided for this image

Recomendación: Transformar las variables de tipo object a un tipo de dato más adecuado para su análisis.

2. Revisión de datos tipo object¶

In [ ]:
df_object = df.select_dtypes(include=['object'])
print('Columnas de tipo object')
for col in df_object.columns:
    print(f"Columna {col} valores únicos -> {df_object[col].unique()[:5]}")
Columnas de tipo object
Columna Date valores únicos -> ['2008-12-01' '2008-12-02' '2008-12-03' '2008-12-04' '2008-12-05']
Columna Location valores únicos -> ['Albury' 'BadgerysCreek' 'Cobar' 'CoffsHarbour' 'Moree']
Columna WindGustDir valores únicos -> ['W' 'WNW' 'WSW' 'NE' 'NNW']
Columna WindDir9am valores únicos -> ['W' 'NNW' 'SE' 'ENE' 'SW']
Columna WindDir3pm valores únicos -> ['WNW' 'WSW' 'E' 'NW' 'W']
Columna RainToday valores únicos -> ['No' 'Yes' nan]
Columna RainTomorrow valores únicos -> ['No' 'Yes']
In [ ]:
# Obtener los valores únicos de la columna 'ubicacion'
valores_unicos = df['Location'].unique()

# Imprimir los valores únicos
print(valores_unicos)
['Albury' 'BadgerysCreek' 'Cobar' 'CoffsHarbour' 'Moree' 'Newcastle'
 'NorahHead' 'NorfolkIsland' 'Penrith' 'Richmond' 'Sydney' 'SydneyAirport'
 'WaggaWagga' 'Williamtown' 'Wollongong' 'Canberra' 'Tuggeranong'
 'MountGinini' 'Ballarat' 'Bendigo' 'Sale' 'MelbourneAirport' 'Melbourne'
 'Mildura' 'Nhil' 'Portland' 'Watsonia' 'Dartmoor' 'Brisbane' 'Cairns'
 'GoldCoast' 'Townsville' 'Adelaide' 'MountGambier' 'Nuriootpa' 'Woomera'
 'Albany' 'Witchcliffe' 'PearceRAAF' 'PerthAirport' 'Perth' 'SalmonGums'
 'Walpole' 'Hobart' 'Launceston' 'AliceSprings' 'Darwin' 'Katherine'
 'Uluru']

Recomendaciones:

  • Date: Se recomienda excluir esta columna del análisis debido a que como valores únicos contamos con solo 5 fechas y además no serán relevantes para la etapa de modelado.
  • Location: Realizar One-Hot Encoding.
  • WindGustDir, WindDir9am y WindDir3pm: Realziar One-Hot Encoding con los valores conocidos.
  • RainToday: Realizar un tratamiento especial para los trabajar datos nulos completando con la moda o eliminandolos. Sumado a lo anterior realizar la conversión a binario.
  • RainTomorrow: Se trata de una de nuestras variables objetvo y se recomienda realizar la conversión a binario.

3. Búsqueda de valores nulos¶

3.1 Datos Nulos porcentual¶
In [ ]:
#Saber porcentaje de valores nulos por columna
null_counts = df.isnull().sum()
null_counts[null_counts > 0].sort_values(ascending=True) / df.shape[0] * 100
Out[ ]:
MaxTemp           0.226453
MinTemp           0.447983
Temp9am           0.635756
WindSpeed9am      0.948007
Rainfall          0.988797
RainToday         0.988797
Humidity9am       1.247600
WindSpeed3pm      1.849599
Temp3pm           1.917113
Humidity3pm       2.538803
WindDir3pm        2.656952
WindGustSpeed     6.519308
WindGustDir       6.561504
WindDir9am        7.041838
Pressure3pm       9.832411
Pressure9am       9.855619
Cloud9am         37.735332
Cloud3pm         40.152469
Evaporation      42.789026
Sunshine         47.692924
dtype: float64
3.2 Datos Nulos por cantidad de valores¶
In [ ]:
null_counts[null_counts > 0].sort_values(ascending=False)
Out[ ]:
Sunshine         67816
Evaporation      60843
Cloud3pm         57094
Cloud9am         53657
Pressure9am      14014
Pressure3pm      13981
WindDir9am       10013
WindGustDir       9330
WindGustSpeed     9270
WindDir3pm        3778
Humidity3pm       3610
Temp3pm           2726
WindSpeed3pm      2630
Humidity9am       1774
RainToday         1406
Rainfall          1406
WindSpeed9am      1348
Temp9am            904
MinTemp            637
MaxTemp            322
dtype: int64
3.3 Análisis de columnas con más de 10% de valores nulos¶
  • Lo primero que haremos es revisar los valores únicos para descartar que los valores nulos representen algo en cada columna y entender los posibles valores
In [ ]:
columns_of_interest = [
    'MaxTemp', 'MinTemp', 'Temp9am', 'WindSpeed9am', 
    'Rainfall', 'RainToday', 'Humidity9am', 
    'WindSpeed3pm', 'Temp3pm', 'Humidity3pm', 'WindDir3pm',
    'WindGustSpeed','WindGustDir','WindDir9am','Pressure3pm','Pressure9am'
]

for column in columns_of_interest:
    unique_values = df[column].unique().tolist()
    print(f"Valores únicos de la columna {column} -> {unique_values}")
Valores únicos de la columna MaxTemp -> [22.9, 25.1, 25.7, 28.0, 32.3, 29.7, 25.0, 26.7, 31.9, 30.1, 30.4, 21.7, 18.6, 21.0, 27.7, 20.9, 22.5, 25.6, 29.3, 33.0, 31.8, 30.9, 32.4, 33.9, 32.7, 27.2, 24.2, 24.4, 26.5, 23.9, 28.8, 34.6, 35.8, 37.9, 38.9, 28.3, 28.4, 30.8, 32.0, 34.7, 37.7, 43.0, 32.2, 36.6, 39.9, 38.1, 34.0, 35.2, 30.6, 34.3, 38.4, 38.2, 40.7, 41.5, 42.9, 42.7, 43.1, 38.3, 36.9, 41.2, 42.2, 44.8, 40.2, 31.2, 27.3, 21.6, 29.0, 29.2, 31.3, 31.1, 29.1, 31.7, 33.2, 29.6, 32.6, 34.5, 30.3, 22.1, 22.0, 24.0, 27.9, 30.2, 30.5, 25.8, 27.0, 19.7, 21.9, 25.3, 33.5, 33.6, 30.0, 31.6, 22.3, 29.8, 27.6, 28.9, 29.9, 32.1, 28.1, 21.4, 24.9, 25.4, 20.0, 23.4, 22.7, 16.2, 15.8, 12.9, 11.5, 14.5, 12.2, 16.5, 17.0, 19.2, 18.9, 19.1, 18.8, 19.3, 18.4, 19.0, 20.5, 19.5, 17.7, 18.5, 15.1, 16.3, 16.6, 16.4, 15.6, 19.8, 21.1, 20.3, 18.1, 15.7, 16.8, 17.1, 14.3, 13.4, 17.4, 16.1, 10.5, 11.6, 12.0, 8.8, 9.6, 8.2, 12.4, 14.9, 15.9, 14.7, 15.3, 17.3, 15.5, 14.1, 13.7, 11.9, 12.3, 13.3, 13.2, 12.1, 12.5, 13.8, 15.0, 13.5, 13.1, 11.0, 12.6, 14.4, 9.8, 12.7, 13.9, 14.8, 15.2, 17.5, 13.6, 12.8, 16.7, 17.9, 11.1, 14.2, 20.7, 16.9, 17.6, 24.7, 17.8, 17.2, 20.4, 20.6, 20.2, 18.2, 18.7, 23.3, 26.6, 27.1, 23.1, 24.1, 26.8, 26.9, 24.3, 23.2, 33.4, 36.0, 35.1, 32.8, 35.4, 36.3, 39.7, 23.6, 32.9, 26.2, 26.4, 31.5, 27.5, 30.7, 27.4, 22.6, 38.6, 40.3, 33.7, 35.9, 36.8, 33.8, 36.4, 39.8, 42.4, 25.2, 37.3, 41.8, 34.4, 36.5, 35.6, 26.1, 28.5, 31.0, 26.3, nan, 25.5, 22.4, 28.6, 31.4, 28.7, 24.8, 19.9, 23.5, 25.9, 23.0, 10.2, 14.0, 8.4, 8.3, 9.4, 10.9, 10.3, 10.8, 14.6, 15.4, 10.0, 10.1, 11.8, 16.0, 10.4, 13.0, 11.7, 10.7, 19.6, 20.1, 20.8, 23.7, 18.0, 21.8, 22.2, 24.5, 29.4, 21.2, 32.5, 28.2, 21.5, 22.8, 11.2, 19.4, 18.3, 9.2, 9.3, 21.3, 23.8, 26.0, 24.6, 27.8, 33.1, 34.9, 36.1, 36.2, 35.3, 35.5, 9.7, 10.6, 11.3, 11.4, 36.7, 37.4, 43.4, 42.0, 40.4, 39.2, 38.8, 37.0, 35.7, 37.1, 29.5, 37.6, 40.5, 39.0, 43.6, 42.6, 34.2, 33.3, 40.6, 41.7, 41.6, 41.1, 40.1, 8.7, 39.6, 34.1, 9.9, 8.6, 9.1, 6.8, 9.5, 9.0, 37.2, 34.8, 40.0, 35.0, 38.0, 39.5, 40.9, 38.5, 7.5, 39.3, 42.5, 43.7, 37.8, 38.7, 41.9, 39.4, 41.4, 37.5, 45.8, 41.0, 39.1, 40.8, 42.8, 45.1, 44.4, 43.5, 42.1, 46.4, 43.9, 45.4, 41.3, 44.3, 46.0, 43.8, 43.2, 45.2, 8.5, 42.3, 7.8, 45.7, 46.6, 47.3, 44.5, 44.1, 44.0, 43.3, 46.5, 44.9, 46.9, 45.3, 44.6, 47.0, 8.9, 8.1, 7.6, 6.3, 8.0, 6.6, 45.5, 4.1, 7.7, 7.1, 7.9, 7.0, 7.3, 2.6, 7.4, 6.2, 7.2, 6.0, 4.9, -1.7, 0.0, 2.4, 5.3, 2.3, 5.7, 5.2, 5.5, 4.7, 6.5, 2.5, 2.7, 3.4, 2.9, 5.0, 3.2, 0.1, -0.1, -2.2, -0.6, 0.6, 2.2, 4.0, 3.5, 3.0, 4.2, 3.3, 3.9, 0.4, 5.9, -0.7, -1.8, -0.2, -1.3, 1.8, 3.1, 1.6, 0.3, 1.2, -0.5, 1.0, 0.5, 0.2, 1.9, 2.0, 5.1, 2.8, 6.7, 0.9, 3.8, 4.3, -2.4, -0.3, 4.6, 6.9, -2.5, 2.1, 1.4, 5.6, 3.6, 4.4, -2.7, -1.0, 5.8, -1.4, -0.8, -2.0, 4.5, 1.7, -0.9, -2.1, -1.5, -3.1, 1.1, -1.2, 4.8, 6.1, 6.4, 3.7, -1.1, 1.5, 5.4, 1.3, 0.8, -2.3, -3.7, -2.9, -0.4, -1.9, -3.8, 0.7, -4.1, -3.2, -3.0, -4.8, 44.2, 46.8, 46.7, 45.0, 46.3, 44.7, 45.6, 46.2, 48.1, 46.1]
Valores únicos de la columna MinTemp -> [13.4, 7.4, 12.9, 9.2, 17.5, 14.6, 14.3, 7.7, 9.7, 13.1, 15.9, 12.6, 9.8, 14.1, 13.5, 11.2, 11.5, 17.1, 20.5, 15.3, 16.2, 16.9, 20.1, 19.7, 12.5, 12.0, 11.3, 9.6, 10.5, 12.3, 13.7, 16.1, 14.0, 17.0, 17.3, 17.2, 17.4, 19.8, 14.9, 13.9, 18.6, 19.3, 24.4, 18.8, 20.8, 15.7, 18.5, 20.4, 21.8, 22.3, 22.0, 28.0, 21.5, 21.7, 23.5, 28.3, 18.4, 12.4, 13.3, 18.0, 18.7, 15.5, 8.9, 15.0, 15.4, 16.0, 12.8, 13.2, 13.8, 7.6, 8.3, 11.0, 20.9, 16.4, 10.0, 8.8, 8.4, 9.3, 14.4, 10.8, 10.1, 9.1, 10.4, 12.2, 10.7, 7.8, 8.1, 7.5, 8.2, 11.6, 13.0, 9.9, 3.5, 6.6, 7.0, 5.7, 6.2, 6.0, 10.6, 8.6, 4.5, 5.4, 2.1, 1.8, 7.2, 4.6, 4.2, 5.2, 4.1, 3.2, 4.3, 3.7, 3.6, 6.9, 10.3, 3.0, 2.6, 5.1, 4.4, 4.7, 6.7, 8.0, 2.2, 1.7, 2.8, 9.0, 6.3, -2.0, -1.3, 2.0, 0.5, 1.2, 0.6, 0.9, 5.0, 3.9, 3.4, 0.0, -1.5, -1.7, -0.4, 0.1, 4.8, 5.9, 2.9, -0.6, -0.3, -1.0, 0.8, -0.1, 1.3, 3.3, 6.5, -0.8, 1.9, 6.8, 2.7, 1.6, 5.5, 7.3, 0.2, 5.8, 7.1, 1.1, 1.0, 6.1, nan, 5.3, 4.0, 11.7, 8.5, 3.8, 6.4, 9.5, 14.5, 15.6, 17.8, 16.7, 18.1, 12.1, 11.4, 18.3, 11.9, 21.0, 11.1, 18.2, 14.2, 11.8, 13.6, 12.7, 15.1, 22.9, 17.6, 21.1, 19.4, 14.8, 16.3, 19.6, 20.6, 24.5, 22.6, 16.8, 8.7, 19.2, 24.7, 17.7, 15.2, 18.9, 17.9, 19.5, 20.3, 23.0, 22.5, 20.2, 16.5, 5.6, 3.1, 1.4, 10.2, 9.4, 0.4, 4.9, 1.5, 2.3, 0.7, -0.5, 2.5, -1.2, 0.3, 2.4, 14.7, 10.9, 16.6, 21.3, 23.2, 21.6, 22.1, 24.0, 19.9, 20.7, 21.9, -0.7, -1.1, -1.4, -0.2, -1.6, 15.8, 19.1, 20.0, -2.5, -1.8, 7.9, 21.2, 22.2, 23.7, 25.2, 19.0, -0.9, -2.1, -2.8, 26.0, -2.4, 26.8, 23.4, 22.8, 22.4, 24.6, 23.9, -3.0, 23.1, 23.6, 21.4, -1.9, 25.1, 24.2, 27.1, 23.3, 24.9, 25.4, 23.8, 27.0, 26.2, 25.0, 24.8, 27.6, 24.1, 27.2, 29.1, 28.9, 25.3, 27.4, 28.8, 27.3, 26.1, 26.5, 22.7, 25.7, 24.3, 29.3, 27.7, 26.3, 25.8, 29.4, 25.6, 26.7, 26.6, 28.1, 27.8, 28.5, 25.5, 26.9, 26.4, 27.5, 28.7, 29.7, 25.9, -2.3, -3.3, -2.2, -3.2, 29.0, 28.6, -3.8, -4.8, -3.1, -2.7, -2.6, -2.9, -4.7, -3.6, -3.5, -3.4, -5.3, -3.7, -5.8, -5.0, -4.5, -4.3, -3.9, -4.2, -4.0, -6.9, -6.5, -5.5, -5.2, -6.3, -4.4, -8.0, -6.7, -4.9, -5.4, -6.1, -4.6, -6.0, -6.6, -5.1, -5.6, -6.8, -7.6, -7.0, -4.1, -5.7, -6.2, -8.2, -5.9, -8.5, -7.1, -6.4, -7.5, -7.2, -7.8, -7.3, 30.5, 29.8, 31.9, 28.4, 28.2, 27.9, 30.7, 33.9, 29.2, 29.9, 31.4, 31.8, 29.5, 31.2, 29.6, 30.3, 31.0, 30.2]
Valores únicos de la columna Temp9am -> [16.9, 17.2, 21.0, 18.1, 17.8, 20.6, 16.3, 18.3, 20.1, 20.4, 15.9, 17.4, 15.8, 17.3, 18.0, 15.5, 19.1, 24.5, 23.8, 20.9, 21.5, 23.2, 26.6, 24.6, 21.6, 12.5, 19.7, 14.9, 17.1, 20.7, 22.4, 23.1, 25.2, 17.9, 20.2, 22.8, 24.2, 24.3, 25.6, 27.6, 16.0, 22.0, 26.8, 27.3, 26.1, 23.3, 21.2, 23.4, 25.8, 28.2, 29.0, 29.2, 29.9, 32.4, 28.8, 27.2, 25.5, 26.5, 28.7, 29.6, 34.5, 18.7, 16.7, 17.0, 19.2, 21.4, 22.1, 19.3, 15.0, 20.0, 22.2, 23.0, 15.6, 13.9, 12.6, 13.3, 17.6, 18.6, 19.0, 19.9, 12.7, 12.2, 12.1, 14.7, 18.8, 15.4, 16.2, 16.5, 14.0, 16.6, 18.4, 12.9, 13.8, 15.1, 16.4, 16.1, 20.5, 9.6, 12.4, 14.1, 11.2, 9.5, 7.6, 10.1, 8.2, 7.9, 7.2, 10.6, 10.3, 10.0, 8.3, 11.0, 9.4, 11.7, 8.5, 9.1, 7.5, 13.0, 7.0, 8.8, 7.4, 11.9, 11.6, 13.6, 7.1, 10.2, 8.0, 9.2, 11.3, 4.7, 6.8, 4.9, 2.2, 1.9, 5.9, 6.5, 5.4, 6.6, 5.6, 6.9, 8.4, 9.8, 13.5, 7.8, 2.3, 2.4, 3.3, 3.8, 4.8, 8.1, 9.0, 4.5, 3.2, 3.7, 2.5, 4.4, 4.2, 9.3, 8.9, 10.5, 9.9, 5.7, 2.0, 14.8, 6.7, 6.0, 5.5, 11.1, 5.8, 10.8, 13.2, 7.7, 9.7, 8.6, 8.7, 10.9, 14.3, 11.5, 13.1, 15.2, 11.8, 13.4, 14.4, 23.9, 17.5, 24.7, 21.7, 24.1, 19.5, 27.8, 16.8, 20.3, 18.9, 15.7, 12.8, 21.8, 20.8, 32.1, 24.4, 26.0, 28.1, 21.3, 26.4, 29.1, 29.4, 25.1, 27.7, 18.5, 25.0, 22.9, 23.5, 26.3, 22.6, 25.9, 19.6, 22.3, 19.8, 14.2, 17.7, 19.4, 18.2, 14.6, 15.3, 10.4, 10.7, 6.4, 6.3, 5.1, 6.2, 5.3, 4.1, 3.4, 6.1, 2.8, 3.1, 3.0, 5.0, 2.9, 5.2, 4.0, 4.6, 4.3, 7.3, 11.4, 13.7, 24.0, 22.5, 21.9, 26.7, 24.9, 25.3, 21.1, 25.4, 24.8, 14.5, 3.5, 3.6, 3.9, 2.6, 12.0, 22.7, 0.3, 27.5, 29.5, 23.6, 30.7, 29.7, 27.0, 23.7, 12.3, nan, 28.6, 26.9, 31.8, 28.0, 30.8, 28.4, 25.7, 27.4, 26.2, 33.7, 27.9, 30.2, 28.3, 2.7, 29.3, 29.8, 1.6, 30.4, 37.6, 34.2, 31.3, 33.6, 31.5, 31.4, 28.9, 30.1, 32.0, 32.6, 35.6, 31.6, 31.2, 30.0, 34.3, 31.1, 37.3, 27.1, 34.4, 33.0, 33.9, 32.9, 34.1, 28.5, 35.7, 31.0, 30.3, 32.3, 35.1, 34.8, 34.0, 37.7, 30.9, 32.2, 33.4, 33.2, 32.7, 30.6, 31.7, 35.2, 30.5, 33.5, 36.8, 34.9, 33.1, 36.3, 32.5, 31.9, 32.8, 35.5, 36.4, 37.5, 35.9, 0.8, 0.9, 36.5, 37.2, 33.3, 0.6, 1.0, 1.7, 2.1, 1.2, 1.8, 0.0, 1.3, 1.5, 0.5, 0.4, 0.2, 1.4, 0.1, -0.9, 0.7, -0.7, -0.2, -0.3, -1.1, 1.1, -1.0, -1.2, -1.3, -0.5, -0.6, -0.4, -0.8, -3.1, -0.1, -1.4, -1.7, -2.3, -2.8, -3.4, -5.9, -2.5, -4.1, -1.6, -2.2, -2.4, -2.9, -2.1, -3.2, -2.0, -1.8, -4.2, -3.3, -4.3, -3.7, -3.6, -5.5, -4.0, -1.9, -4.8, -2.7, -5.2, -5.3, -1.5, -3.9, -3.0, -3.8, -4.4, -2.6, -6.2, -3.5, -4.5, -5.6, -7.0, -7.2, 36.0, 35.4, 34.6, 33.8, 36.9, 35.3, 36.1, 38.3, 37.4, 34.7, 38.6, 35.8, 37.9, 35.0, 40.2, 37.0, 39.4, 39.0, 38.2, 36.2, 38.9, 36.6, 39.1, 38.0]
Valores únicos de la columna WindSpeed9am -> [20.0, 4.0, 19.0, 11.0, 7.0, 6.0, 15.0, 17.0, 28.0, 24.0, nan, 9.0, 0.0, 13.0, 2.0, 26.0, 30.0, 22.0, 35.0, 37.0, 31.0, 33.0, 48.0, 39.0, 44.0, 41.0, 46.0, 43.0, 56.0, 83.0, 74.0, 52.0, 65.0, 50.0, 130.0, 54.0, 61.0, 57.0, 59.0, 87.0, 67.0, 63.0, 69.0, 72.0]
Valores únicos de la columna Rainfall -> [0.6, 0.0, 1.0, 0.2, 1.4, 2.2, 15.6, 3.6, nan, 16.8, 10.6, 1.2, 0.8, 6.4, 0.4, 3.0, 5.8, 11.6, 1.8, 8.6, 12.6, 8.4, 6.2, 20.0, 21.0, 3.2, 4.8, 4.2, 8.0, 14.4, 4.6, 2.0, 5.6, 1.6, 6.0, 4.4, 5.4, 5.0, 7.8, 6.8, 9.8, 3.8, 2.4, 5.2, 6.6, 13.4, 10.2, 28.8, 7.0, 25.8, 9.4, 12.4, 52.2, 20.6, 66.0, 11.0, 17.0, 10.4, 28.0, 21.4, 18.6, 7.2, 8.2, 10.8, 15.4, 9.6, 4.0, 21.8, 20.8, 24.8, 10.0, 11.4, 19.0, 22.2, 32.8, 3.4, 50.8, 52.6, 19.2, 18.8, 14.8, 12.0, 18.4, 25.6, 35.0, 14.2, 13.8, 2.6, 99.2, 51.0, 39.8, 28.2, 12.2, 12.8, 11.8, 19.8, 17.4, 8.8, 16.2, 14.6, 2.8, 30.8, 28.4, 34.8, 44.0, 14.0, 16.6, 9.0, 26.8, 38.4, 104.2, 36.6, 34.2, 29.4, 27.2, 11.2, 13.2, 33.4, 7.6, 24.6, 7.4, 16.0, 19.4, 53.4, 15.0, 33.6, 17.2, 37.4, 13.0, 31.0, 9.2, 66.2, 36.4, 41.0, 24.4, 27.0, 46.8, 15.8, 35.8, 22.4, 16.4, 15.2, 23.0, 22.8, 28.6, 46.0, 24.2, 22.0, 18.0, 31.2, 21.2, 36.0, 23.4, 32.0, 46.4, 13.6, 42.0, 33.8, 25.4, 20.4, 22.6, 43.2, 61.4, 48.2, 48.6, 18.2, 67.8, 39.2, 31.8, 82.4, 35.4, 116.0, 30.6, 17.8, 38.2, 30.2, 24.0, 47.0, 42.4, 33.0, 40.0, 44.2, 34.6, 30.4, 38.8, 83.6, 50.2, 26.2, 38.0, 31.6, 27.8, 29.8, 17.6, 100.2, 109.2, 23.6, 32.6, 21.6, 54.0, 39.6, 26.0, 34.0, 49.4, 37.0, 29.2, 68.0, 33.2, 27.4, 39.0, 38.6, 43.0, 4.5, 29.1, 2.9, 1.3, 30.0, 63.6, 189.0, 58.6, 59.0, 20.2, 42.8, 76.0, 19.6, 55.8, 70.0, 71.2, 141.8, 96.0, 371.0, 58.0, 67.0, 80.6, 56.6, 45.2, 59.4, 42.6, 34.4, 90.0, 128.0, 61.2, 23.8, 27.6, 73.8, 72.2, 105.4, 40.4, 102.0, 44.4, 48.0, 63.8, 36.8, 5.5, 25.2, 103.4, 127.6, 63.2, 52.4, 25.0, 55.0, 56.8, 70.8, 62.4, 112.0, 153.2, 45.8, 97.0, 51.8, 86.4, 0.5, 159.8, 208.5, 172.2, 0.9, 2.5, 0.3, 1.7, 3.3, 51.2, 106.4, 147.8, 45.6, 59.6, 29.0, 11.7, 75.0, 76.4, 64.0, 53.2, 100.4, 0.1, 65.8, 8.5, 32.4, 157.8, 4.1, 113.8, 0.7, 3.1, 1.5, 32.2, 32.7, 10.1, 11.1, 96.1, 49.8, 219.6, 109.4, 3.5, 26.4, 29.6, 36.2, 37.6, 43.8, 41.5, 50.6, 142.8, 106.2, 104.8, 2.7, 31.1, 13.9, 71.0, 90.6, 64.8, 47.6, 51.4, 26.6, 48.8, 37.2, 39.4, 113.0, 74.4, 92.8, 40.2, 76.8, 54.6, 44.8, 44.6, 50.0, 22.7, 20.9, 59.8, 45.4, 147.2, 35.2, 71.4, 31.4, 23.7, 42.2, 75.6, 41.8, 43.6, 4.9, 35.6, 26.5, 49.0, 33.9, 30.7, 5.3, 10.7, 64.1, 50.4, 45.5, 6.9, 68.8, 77.6, 89.8, 69.8, 32.5, 62.6, 132.5, 15.7, 22.5, 240.0, 41.2, 6.3, 58.2, 37.9, 29.5, 52.0, 21.5, 216.3, 12.5, 2.3, 51.6, 20.7, 63.4, 74.2, 23.2, 43.4, 56.0, 47.8, 48.4, 69.2, 55.6, 61.8, 73.0, 83.4, 37.8, 126.4, 47.2, 59.2, 120.2, 56.2, 89.0, 76.2, 82.8, 69.6, 72.0, 40.8, 107.4, 71.6, 29.9, 142.2, 79.8, 84.8, 105.6, 57.6, 45.0, 62.2, 111.0, 40.6, 122.6, 54.8, 61.0, 61.6, 156.8, 39.9, 2.1, 1.9, 1.1, 4.7, 5.7, 92.2, 115.4, 101.8, 49.6, 85.6, 81.4, 81.6, 67.6, 58.4, 41.6, 56.4, 111.8, 47.4, 113.4, 74.0, 70.6, 78.4, 68.6, 77.4, 73.2, 99.4, 65.2, 88.2, 57.4, 95.2, 57.0, 119.4, 105.8, 54.4, 41.4, 94.4, 64.4, 93.8, 68.4, 52.8, 85.0, 83.2, 106.0, 60.2, 91.0, 53.6, 104.6, 80.4, 106.8, 88.6, 72.8, 62.8, 46.6, 95.6, 53.0, 54.2, 110.8, 57.8, 12.3, 22.9, 13.3, 134.8, 84.4, 46.2, 64.2, 86.8, 157.6, 166.8, 156.0, 114.4, 81.8, 225.0, 8.7, 91.4, 18.1, 49.2, 60.8, 97.2, 82.6, 78.6, 53.8, 72.6, 139.0, 58.8, 65.0, 79.0, 75.8, 55.2, 192.0, 80.8, 118.0, 96.4, 164.2, 69.4, 75.2, 55.4, 87.0, 93.0, 91.6, 84.2, 87.6, 78.0, 73.4, 102.2, 60.4, 89.4, 107.6, 83.8, 78.2, 88.0, 66.4, 82.2, 155.0, 60.0, 65.6, 63.0, 84.0, 87.4, 83.0, 73.6, 77.2, 79.4, 121.4, 60.6, 93.6, 168.4, 145.0, 94.0, 89.2, 68.2, 182.6, 110.6, 98.0, 278.4, 140.2, 62.0, 121.6, 71.8, 115.8, 79.2, 268.6, 183.0, 109.6, 128.2, 206.2, 136.6, 150.2, 161.6, 109.0, 115.2, 175.2, 247.2, 85.4, 105.2, 74.8, 115.0, 126.0, 84.6, 158.0, 77.8, 64.6, 118.2, 143.8, 118.6, 112.2, 178.2, 183.4, 108.2, 111.2, 128.4, 80.2, 129.0, 105.0, 177.6, 86.2, 236.8, 93.4, 79.6, 206.8, 81.2, 92.6, 165.2, 170.4, 93.2, 98.2, 148.6, 70.2, 144.2, 164.6, 174.6, 70.4, 87.8, 124.8, 120.8, 78.8, 76.6, 11.9, 9.5, 10.5, 7.1, 6.5, 6.1, 34.3, 3.9, 6.7, 12.7, 14.5, 29.3, 23.9, 8.9, 9.1, 13.1, 10.9, 18.5, 65.4, 47.3, 5.9, 19.7, 12.1, 11.5, 7.5, 7.9, 25.3, 17.5, 7.3, 9.9, 15.5, 15.9, 81.0, 95.8, 90.4, 141.2, 162.2, 136.4, 131.4, 132.6, 367.6, 184.6, 182.2, 145.2, 96.8, 74.6, 129.4, 122.8, 109.8, 145.6, 210.6, 117.6, 69.5, 167.0, 69.0]
Valores únicos de la columna RainToday -> ['No', 'Yes', nan]
Valores únicos de la columna Humidity9am -> [71.0, 44.0, 38.0, 45.0, 82.0, 55.0, 49.0, 48.0, 42.0, 58.0, 89.0, 76.0, 65.0, 50.0, 69.0, 80.0, 47.0, 56.0, 54.0, 41.0, 78.0, 46.0, 43.0, 33.0, 34.0, 36.0, 52.0, 51.0, 40.0, 35.0, 39.0, 60.0, 37.0, 27.0, 32.0, 53.0, 20.0, 66.0, 63.0, 57.0, 62.0, 87.0, 61.0, 59.0, 92.0, 72.0, 67.0, 75.0, 88.0, 68.0, 73.0, 74.0, 83.0, 77.0, 70.0, 81.0, 86.0, 97.0, 99.0, 91.0, 85.0, 93.0, 84.0, 94.0, 79.0, 98.0, 96.0, 95.0, 90.0, 64.0, 29.0, 21.0, 100.0, 24.0, nan, 25.0, 31.0, 18.0, 23.0, 26.0, 28.0, 30.0, 19.0, 22.0, 17.0, 15.0, 9.0, 12.0, 13.0, 16.0, 6.0, 10.0, 14.0, 11.0, 7.0, 8.0, 5.0, 3.0, 2.0, 4.0, 0.0, 1.0]
Valores únicos de la columna WindSpeed3pm -> [24.0, 22.0, 26.0, 9.0, 20.0, 17.0, 28.0, 11.0, 6.0, 13.0, 19.0, 30.0, 31.0, 7.0, 15.0, 48.0, 4.0, 33.0, 0.0, 2.0, nan, 37.0, 46.0, 39.0, 50.0, 35.0, 44.0, 41.0, 43.0, 56.0, 61.0, 54.0, 52.0, 83.0, 65.0, 78.0, 57.0, 63.0, 59.0, 74.0, 72.0, 69.0, 76.0, 87.0, 67.0]
Valores únicos de la columna Temp3pm -> [21.8, 24.3, 23.2, 26.5, 29.7, 28.9, 24.6, 25.5, 30.2, 28.2, 28.8, 17.0, 15.8, 19.8, 26.2, 18.1, 21.5, 21.0, 27.3, 31.6, 30.8, 29.0, 31.2, 33.0, 32.1, 26.1, 18.2, 22.7, 25.7, 22.1, 33.9, 34.4, 36.8, 38.4, 27.6, 26.6, 29.3, 30.0, 33.2, 35.7, 41.5, 27.1, 25.8, 30.5, 37.7, 36.1, 33.1, 36.5, 36.2, 39.2, 40.1, 41.2, 42.0, 41.9, 37.1, 35.2, 39.7, 41.6, 43.4, 38.5, 29.4, 24.9, 17.3, 28.5, 29.2, 29.5, 27.0, 30.7, 32.7, 26.8, 29.8, 31.3, 33.4, 28.6, 33.6, 28.1, 21.9, 21.4, 22.0, 29.6, 18.8, 23.8, 19.7, 18.3, 20.5, 23.9, 27.2, 32.6, 33.5, 31.4, 19.6, 27.7, 29.9, 30.9, 27.4, 20.3, 21.2, 20.9, 21.6, 23.5, 25.0, 24.4, 23.1, 18.9, 19.4, 22.9, 23.6, 21.3, 22.3, 22.6, 15.1, 14.5, 11.6, 9.4, 14.0, 12.1, 16.1, 16.3, 19.1, 18.5, 18.4, 19.2, 20.2, 17.7, 18.0, 14.6, 15.3, 15.9, 14.7, 18.7, 21.7, 20.8, 19.5, 17.4, 15.6, 16.7, 16.8, 13.4, 13.0, 16.5, 10.2, 11.5, 11.4, 7.9, 9.7, 8.8, 15.5, 13.9, 15.4, 14.9, 16.4, 13.6, 15.2, 13.7, 11.3, 12.3, 13.1, 11.7, 12.6, 12.0, 12.4, 14.3, 13.2, 10.1, 12.5, 12.8, 14.2, 11.2, 13.5, 17.6, 12.9, 10.8, 9.6, 7.3, 12.7, 13.3, 16.6, 11.1, 14.4, 16.2, 17.5, 10.7, 16.0, 24.0, 17.1, 20.7, 17.2, 20.6, 14.8, 10.0, 15.7, 17.8, 19.0, 14.1, 10.9, 19.3, 25.3, 25.4, 24.8, 23.4, 28.4, 30.3, 31.1, 32.8, 33.8, 34.9, 34.6, 31.7, 35.4, 39.0, 36.4, 25.6, 32.0, 25.2, 24.7, 28.7, 30.6, 26.0, 32.5, 36.9, 30.4, 35.9, 37.5, 27.5, 34.1, 35.1, 28.0, 31.8, 35.3, 38.6, 40.9, 41.1, 19.9, 36.0, 24.1, 34.3, 39.1, 34.7, 34.8, 30.1, 32.9, 26.4, 24.2, 20.1, 21.1, 22.8, 31.5, 26.9, 29.1, 28.3, 25.1, 23.0, 22.4, 27.9, 18.6, 16.9, 13.8, 15.0, 8.9, 11.0, 11.8, 8.2, 9.1, 10.4, 12.2, 8.7, 11.9, 22.5, 24.5, 36.7, 37.3, 38.8, 26.7, 8.6, 20.4, 9.0, 10.3, 10.6, 8.0, 8.1, 10.5, 9.8, 9.5, 9.9, 17.9, 22.2, 23.3, 23.7, 26.3, nan, 25.9, 35.0, 34.2, 34.5, 32.4, 27.8, 20.0, 7.0, 35.8, 39.3, 42.4, 40.7, 38.2, 40.6, 35.6, 34.0, 36.3, 32.3, 9.2, 9.3, 8.3, 31.9, 41.7, 38.9, 31.0, 37.2, 40.8, 40.2, 38.3, 8.4, 8.5, 6.7, 32.2, 37.0, 7.6, 6.4, 7.7, 33.3, 39.5, 37.6, 42.3, 33.7, 35.5, 7.5, 7.4, 38.0, 39.8, 37.8, 39.6, 40.3, 36.6, 42.2, 37.9, 43.7, 38.7, 41.0, 43.5, 43.3, 38.1, 43.0, 41.4, 40.0, 40.4, 37.4, 39.9, 43.2, 40.5, 44.8, 42.9, 42.6, 42.1, 42.7, 43.1, 39.4, 6.9, 44.0, 45.2, 45.8, 41.3, 42.8, 46.7, 45.3, 44.1, 42.5, 43.8, 46.2, 45.9, 44.7, 44.9, 41.8, 6.8, 6.0, 6.6, 43.9, 7.1, 7.8, 7.2, 5.7, 5.1, 6.2, 3.7, 6.5, 6.1, 4.3, 5.4, 5.3, 4.9, 5.6, 2.3, 5.5, 6.3, 5.9, 5.8, 3.4, 3.6, -1.9, -1.3, 1.4, 4.4, 4.5, 2.6, 0.8, 4.8, 1.8, 2.4, 2.7, 4.0, 5.0, -0.3, -2.9, -5.1, -0.4, 0.9, 2.1, 2.9, 1.2, -0.6, 1.9, 5.2, -0.7, -1.0, -1.8, -0.1, -1.6, -0.2, 1.6, 1.3, -1.2, 2.0, 2.8, 0.7, -0.9, 0.3, -1.1, 1.1, 1.0, 0.0, -2.8, -1.4, 0.2, 0.4, -3.1, -2.6, 3.0, 0.6, 4.6, 3.2, 4.2, 3.5, 3.8, 4.1, -1.7, -1.5, 3.3, 2.2, -2.0, -2.2, 2.5, -2.3, 3.9, 3.1, -3.7, 4.7, 1.7, 0.1, 1.5, -3.9, -0.5, -2.7, -3.5, -2.1, 0.5, -2.5, -3.2, -4.1, -3.4, -0.8, -3.0, -4.4, -2.4, -4.0, -4.2, -5.4, -3.8, 44.4, 46.1, 45.4, 43.6, 44.5, 44.3, 45.0]
Valores únicos de la columna Humidity3pm -> [22.0, 25.0, 30.0, 16.0, 33.0, 23.0, 19.0, 9.0, 27.0, 91.0, 93.0, 43.0, 28.0, 82.0, 65.0, 32.0, 26.0, 24.0, 17.0, 15.0, 70.0, 12.0, 8.0, 31.0, 20.0, 10.0, 21.0, 39.0, 13.0, 11.0, 69.0, 18.0, 14.0, 35.0, 90.0, 68.0, 74.0, 41.0, 34.0, 78.0, 49.0, 37.0, 42.0, 47.0, 52.0, 29.0, 86.0, 89.0, 62.0, 79.0, 48.0, 46.0, 38.0, 44.0, 51.0, 36.0, 45.0, 40.0, 53.0, 61.0, 59.0, 63.0, 54.0, 57.0, 50.0, 58.0, 75.0, 97.0, 80.0, 95.0, 56.0, 72.0, 60.0, 71.0, 73.0, 81.0, 76.0, 64.0, 87.0, 85.0, 67.0, 55.0, 77.0, 84.0, 7.0, 99.0, 92.0, 66.0, 83.0, 94.0, 96.0, 88.0, nan, 100.0, 98.0, 5.0, 6.0, 1.0, 4.0, 2.0, 3.0, 0.0]
Valores únicos de la columna WindDir3pm -> ['WNW', 'WSW', 'E', 'NW', 'W', 'SSE', 'ESE', 'ENE', 'NNW', 'SSW', 'SW', 'SE', 'N', 'S', 'NNE', nan, 'NE']
Valores únicos de la columna WindGustSpeed -> [44.0, 46.0, 24.0, 41.0, 56.0, 50.0, 35.0, 80.0, 28.0, 30.0, 31.0, 61.0, 22.0, 63.0, 43.0, 26.0, 33.0, 57.0, 48.0, 39.0, 37.0, 52.0, 98.0, 54.0, 83.0, nan, 59.0, 70.0, 69.0, 17.0, 20.0, 19.0, 15.0, 13.0, 11.0, 72.0, 85.0, 65.0, 78.0, 107.0, 74.0, 67.0, 94.0, 76.0, 81.0, 87.0, 9.0, 7.0, 89.0, 91.0, 93.0, 102.0, 100.0, 113.0, 117.0, 96.0, 111.0, 106.0, 135.0, 104.0, 120.0, 115.0, 126.0, 109.0, 122.0, 124.0, 130.0, 6.0]
Valores únicos de la columna WindGustDir -> ['W', 'WNW', 'WSW', 'NE', 'NNW', 'N', 'NNE', 'SW', 'ENE', 'SSE', 'S', 'NW', 'SE', 'ESE', nan, 'E', 'SSW']
Valores únicos de la columna WindDir9am -> ['W', 'NNW', 'SE', 'ENE', 'SW', 'SSE', 'S', 'NE', nan, 'SSW', 'N', 'WSW', 'ESE', 'E', 'NW', 'WNW', 'NNE']
Valores únicos de la columna Pressure3pm -> [1007.1, 1007.8, 1008.7, 1012.8, 1006.0, 1005.4, 1008.2, 1010.1, 1003.6, 1005.7, 1004.2, 993.0, 1001.8, 1010.3, 1010.4, 1002.2, 1009.7, 1017.1, 1014.8, 1008.1, 1007.6, 1001.7, 1003.4, 1005.1, 1003.2, 1013.1, 1009.2, 1006.7, 1002.7, 1010.9, 1013.7, 1006.8, 1012.1, 1006.9, 1012.7, 1017.4, 1016.2, 1010.6, 1004.8, 1005.9, 997.8, 1003.9, 1014.6, 1014.1, 1011.6, 1011.8, 1010.2, 1010.5, 1007.4, 1004.7, 1002.6, 1005.0, 1003.8, 1006.5, 1008.5, 1011.1, 1017.3, 1019.7, 1016.4, 1013.8, 1013.5, 1007.5, 1004.5, 1010.8, 1012.4, 1013.4, 1015.0, 1012.6, 1004.6, 1009.0, 1012.0, 1014.7, 1015.9, 1018.0, 1018.9, 1008.0, 1013.2, 1013.9, 1013.6, 1014.4, 1019.2, 1017.2, 1020.7, 1020.6, 1019.1, 1019.5, 1019.4, 1018.4, 1012.9, 1019.3, 1016.5, 1019.6, 1023.5, 1023.4, 1017.7, 1020.3, 1020.8, 1018.7, 1009.8, 1016.8, 1020.0, 1020.9, 1021.6, 1015.7, 1002.4, 1000.9, 1003.3, 1018.3, 1021.5, 1023.2, 1024.0, 1025.9, 1027.3, 1028.1, 1024.6, 1023.6, 1025.8, 1021.8, 1022.3, 1022.2, 1018.5, 1011.0, 1021.2, 1019.9, 1020.5, 1021.4, 1022.1, 1028.5, 1029.9, 1029.2, 1026.2, 1020.4, 1017.5, 1015.1, 1006.3, 1008.3, 1023.0, 1013.0, 1009.3, 1027.7, 1028.6, 1027.1, 1018.6, 1005.5, 1006.6, 1009.4, 1001.0, 1005.2, 1009.6, 1014.9, 1019.0, 1023.8, 1015.6, 1007.7, 1005.8, 1009.9, 1014.5, 1019.8, 1006.2, 1025.4, 1022.7, 1023.1, 1025.3, 1024.8, 1022.9, 1020.2, 1016.7, 1008.6, 1010.0, 1015.3, 1006.4, 1027.2, 1022.5, 1014.3, 1013.3, 996.9, 1015.2, 1021.7, 1012.3, 1017.9, 1011.4, 1011.3, 1018.2, 1015.4, 1012.2, 1011.9, 999.2, 1002.9, 1008.4, 1008.8, 1004.9, 1025.7, 1016.9, 999.4, 997.6, 1024.7, 1023.7, 1017.6, 1022.0, 1015.8, 1017.8, 1011.2, 1002.3, 1003.5, 1016.0, 1016.3, 1016.1, 1014.2, 1007.3, 1017.0, 1012.5, 1011.5, 1009.1, 1004.1, 1007.0, 1003.7, 1007.9, 1011.7, 1021.3, 1030.2, 1033.6, 1031.4, 1026.0, 1021.0, 1023.3, 1018.8, 1018.1, 1021.1, 1020.1, 1024.4, 1021.9, 1014.0, 1024.1, 1024.3, 1015.5, 1002.8, 1030.7, 1032.0, 1028.3, 1026.7, 1033.8, 1035.2, 1032.9, 1029.8, 1029.0, 1022.8, 1025.1, 1026.6, 1008.9, 1026.3, 1028.9, 1029.1, 1034.1, 1031.5, 1000.1, 1004.4, 1025.2, 999.0, 1022.6, 1025.0, 1023.9, 982.9, 1007.2, 1002.1, 994.3, 1004.3, 1000.5, 1010.7, 1009.5, 1006.1, 1001.5, 1016.6, 1002.5, 1000.3, 1005.3, 1030.5, 1028.8, 1024.9, 1024.5, 1027.8, 1028.7, 1032.6, 1035.1, 1034.2, 1029.7, 1033.3, 1027.6, 1030.4, 1034.6, 1036.0, 996.2, 1030.9, 1026.1, nan, 1000.7, 995.4, 1002.0, 995.7, 1001.9, 1031.0, 1031.1, 1031.9, 1032.5, 1025.5, 1028.4, 1033.2, 1024.2, 1030.3, 1030.0, 1001.3, 1000.8, 1001.6, 1026.9, 997.2, 998.5, 1026.8, 1027.9, 1028.2, 1029.3, 1022.4, 1027.4, 1029.4, 999.6, 1001.4, 999.1, 994.8, 1001.2, 998.4, 1025.6, 1026.5, 1003.0, 998.9, 998.8, 1026.4, 1027.5, 1030.1, 1032.3, 1032.8, 1005.6, 998.7, 1000.2, 1033.5, 1032.2, 1030.6, 1031.7, 1028.0, 1032.1, 1031.2, 1029.5, 1004.0, 1036.1, 999.5, 993.1, 998.1, 997.5, 1000.0, 995.9, 1034.3, 1033.7, 1031.3, 1032.4, 998.0, 1000.6, 998.2, 1001.1, 999.3, 1003.1, 1034.9, 1036.2, 1032.7, 1031.8, 995.1, 1036.4, 1035.0, 1034.8, 1036.8, 996.4, 1031.6, 997.7, 1027.0, 997.9, 996.7, 999.8, 999.7, 995.3, 994.5, 996.5, 998.3, 1030.8, 993.8, 997.4, 995.8, 1029.6, 1034.0, 993.7, 999.9, 997.1, 1000.4, 1034.7, 991.6, 1034.4, 1033.4, 1035.9, 996.8, 997.0, 1035.6, 995.5, 1034.5, 1035.7, 995.6, 994.9, 996.1, 979.0, 996.0, 995.2, 1033.0, 989.0, 1036.3, 1035.5, 993.4, 994.0, 996.3, 998.6, 1026.66, 1009.555, 1016.777, 991.4, 991.0, 990.3, 989.8, 1036.7, 994.2, 989.3, 995.0, 1037.0, 1035.4, 993.9, 993.6, 984.2, 994.7, 997.3, 994.4, 992.8, 990.7, 1033.1, 987.4, 1036.9, 1035.8, 1037.8, 1033.9, 993.5, 993.3, 990.2, 993.2, 1037.3, 985.5, 1037.9, 996.6, 994.1, 991.9, 992.6, 985.0, 994.6, 1037.5, 1037.7, 990.9, 988.7, 992.5, 989.9, 987.3, 992.0, 990.4, 988.6, 992.7, 992.3, 987.1, 991.8, 991.1, 988.8, 991.5, 992.9, 991.7, 989.4, 992.4, 992.1, 1035.3, 988.2, 990.8, 990.6, 988.3, 987.7, 982.6, 986.5, 991.3, 1036.6, 1037.1, 985.6, 992.2, 987.8, 986.0, 1036.5, 985.2, 986.4, 986.6, 988.9, 984.9, 1038.0, 1038.2, 986.9, 989.6, 989.7, 989.2, 986.1, 985.1, 984.0, 985.3, 981.2, 988.4, 1037.2, 1037.6, 987.6, 980.2, 986.2, 987.0, 1038.5, 1038.9, 988.1, 990.1, 988.5, 990.0, 984.5, 987.2, 985.4, 981.4, 984.4, 989.1, 991.2, 982.2, 988.0, 977.1, 978.2, 983.2, 981.9, 983.3, 990.5, 1039.6, 986.8, 1038.4, 985.8, 989.5]
Valores únicos de la columna Pressure9am -> [1007.7, 1010.6, 1007.6, 1017.6, 1010.8, 1009.2, 1009.6, 1013.4, 1008.9, 1007.0, 1011.8, 1010.5, 994.3, 1001.2, 1012.2, 1005.8, 1009.4, 1019.2, 1019.3, 1013.6, 1007.8, 1011.0, 1012.9, 1010.9, 1006.8, 1005.2, 1004.8, 1005.6, 1006.1, 1004.5, 1014.4, 1018.7, 1015.1, 1012.6, 1011.9, 1017.8, 1009.9, 1014.1, 1015.7, 1011.6, 1008.4, 1019.7, 1015.8, 1010.1, 1005.3, 1007.9, 1005.4, 1016.5, 1017.7, 1014.9, 1014.6, 1014.2, 1012.5, 1011.7, 1008.8, 1005.9, 1008.0, 1008.2, 1009.3, 1012.8, 1017.0, 1023.3, 1022.5, 1016.2, 1017.2, 1012.4, 1015.6, 1013.0, 1014.0, 1016.6, 1007.5, 1014.7, 1014.5, 1013.7, 1015.2, 1019.5, 1021.3, 1017.4, 1012.7, 1013.3, 1016.3, 1014.8, 1019.1, 1023.0, 1023.8, 1022.4, 1023.2, 1022.6, 1018.8, 1019.8, 1020.4, 1021.8, 1026.7, 1027.1, 1024.2, 1021.5, 1024.4, 1024.1, 1018.5, 1022.8, 1022.7, 1023.6, 1025.2, 1026.0, 1004.0, 1013.8, 1018.0, 1023.1, 1023.4, 1026.9, 1028.7, 1029.8, 1031.4, 1028.5, 1026.2, 1028.8, 1025.1, 1025.6, 1022.3, 1018.4, 1015.3, 1015.0, 1024.7, 1022.2, 1025.0, 1024.6, 1021.4, 1021.7, 1030.3, 1034.1, 1031.9, 1029.3, 1023.5, 1021.0, 1017.9, 1011.1, 1025.7, 1018.3, 1013.9, 1029.7, 1031.6, 1030.8, 1021.9, 1020.7, 1020.2, 1015.5, 1011.4, 1006.5, 1008.6, 1019.9, 1030.4, 1032.0, 1020.5, 1010.4, 1006.6, 1021.6, 1009.5, 1027.3, 1026.8, 1024.0, 1025.8, 1027.9, 1026.4, 1018.6, 1009.0, 1011.5, 1021.1, 1021.2, 1018.2, 1027.7, 1012.0, 1004.1, 1016.1, 1016.9, 1002.6, 1018.9, 1024.9, 1005.0, 1020.0, 997.8, 1009.8, 1012.3, 1020.6, 1029.5, 1001.9, 1000.5, 1008.5, 1016.0, 1026.6, 1022.9, 1020.8, 1019.6, 1027.5, 1025.4, 1017.1, 1029.1, 1010.0, 1003.7, 1010.7, 1010.3, 1022.0, 1015.9, 1006.9, 1019.4, 1018.1, 1013.5, 1016.8, 1017.5, 1015.4, 1006.7, 1013.2, 1016.4, 1017.3, 1020.3, 1023.9, 1016.7, 1008.7, 1036.3, 1035.2, 1030.0, 1025.5, 1022.1, 1026.5, 1027.8, 1020.9, 1023.7, 1005.7, 1004.7, 1031.8, 1032.3, 1027.4, 1027.2, 1034.5, 1037.3, 1036.9, 1030.1, 1024.3, 1027.6, 1030.5, 1032.5, 1030.9, 1029.2, 1032.7, 1035.5, 1032.1, 1031.7, 1035.9, 1036.1, 1024.5, 1006.2, 1003.1, 1029.6, 1028.9, 1024.8, 1026.1, 1026.3, 1028.2, 1028.4, 1025.3, 1029.4, 989.8, 1004.6, 1011.3, 1014.3, 1012.1, 1009.1, 1002.4, 998.8, 1002.3, 1006.0, 1009.7, 1004.4, 1007.4, 1002.5, 1019.0, 1020.1, 1001.4, 1031.5, 1033.0, 1002.9, 1025.9, 1028.0, 1027.0, 1002.0, 1028.3, 1031.0, 1035.7, 1037.4, 1038.9, 1033.6, 1036.6, 1031.3, 1010.2, 1039.9, 1013.1, 996.3, 1032.4, 1033.4, 1011.2, 1004.3, 1007.2, 1006.3, 995.3, 1000.9, 1005.5, 1030.2, 1035.1, 1033.8, 1036.5, 1034.4, 1003.3, 1031.1, 1031.2, 1029.0, 1028.6, 1033.1, 1033.2, 1007.3, 1000.8, 999.9, 1007.1, 1028.1, 1033.7, 1030.7, 1033.3, 1008.1, 1002.2, 1003.0, 1006.4, 1008.3, 998.9, 1000.7, 998.4, 1033.5, 1004.9, 1003.2, 1034.0, 1035.6, 1035.0, 1032.2, 1032.6, 1000.4, 1029.9, 1037.8, 1034.3, 1034.7, 1035.3, 1036.0, 1003.9, 1032.8, 1004.2, 1002.8, 996.0, 1003.4, 1037.5, 1038.2, 1034.8, 1000.1, 1032.9, 1033.9, 1003.6, 993.7, 992.9, 1000.3, 1001.3, 999.4, 1005.1, 996.6, 1036.8, 1030.6, 997.6, 1001.7, 1001.0, nan, 1036.2, 1035.4, 1037.6, 1038.0, 1003.5, 1001.5, 1038.6, 997.4, 1034.2, 1003.8, 997.3, 999.3, 996.8, 1037.0, 1034.9, 1039.2, 998.5, 998.6, 991.7, 1001.1, 1002.1, 1035.8, 1002.7, 998.3, 999.7, 999.0, 1037.1, 1001.6, 996.5, 997.2, 999.6, 1038.3, 1038.4, 1000.6, 999.2, 980.5, 1000.2, 994.9, 999.8, 1001.8, 994.6, 1037.9, 1038.7, 998.0, 999.1, 997.0, 1034.6, 1038.8, 1039.1, 990.2, 986.7, 995.0, 1036.7, 996.7, 999.5, 1039.0, 998.1, 1038.1, 997.7, 991.5, 1039.6, 998.7, 1000.0, 1037.7, 994.5, 994.8, 994.0, 996.1, 994.7, 997.1, 1037.2, 1036.4, 998.2, 987.4, 993.9, 996.9, 1039.3, 1039.5, 995.2, 1040.1, 1040.2, 1040.6, 996.4, 1040.3, 995.7, 995.4, 992.8, 996.2, 994.2, 1039.4, 995.9, 995.8, 997.9, 990.5, 993.3, 989.4, 992.0, 995.1, 992.5, 989.5, 991.2, 991.4, 992.1, 997.5, 993.0, 992.7, 989.3, 991.6, 993.8, 993.4, 995.5, 989.7, 993.6, 988.9, 992.4, 991.8, 993.5, 994.1, 991.3, 1038.5, 986.9, 990.3, 995.6, 993.2, 990.9, 994.4, 990.8, 991.1, 992.6, 986.2, 982.3, 989.6, 985.1, 982.0, 989.2, 1040.9, 992.3, 1041.0, 1040.4, 989.0, 988.3, 986.3, 988.0, 984.6, 992.2, 987.2, 982.9, 988.5, 989.1, 988.8, 987.0, 993.1, 1040.0, 991.9, 983.7, 985.8, 985.9, 987.3, 991.0, 987.1, 990.4, 986.6, 988.1, 988.2, 989.9, 982.2, 984.4, 983.9, 985.0, 1040.5, 1039.7, 987.9, 990.6]

Recomendaciones:

  • Las columnas con menos de 10%, teniendo el contexto del caso, lo mejor sería utilizar KNNImputer o DecisionTree debido a la relevancia que tendrá cada variable pero debido al bajo porcentaje podría decidirse imputar por la moda o promedio.
  • También se recomienda castear las columnas RainToday, WindDir3pm, WindGustDir y WindDir9am con One-Hot Encoding
3.3 Análisis de columnas con menos de 10% de valores nulos¶
  • Lo primero que haremos es revisar los valores únicos para descartar que los valores nulos representen algo en cada columna y entender los posibles valores
In [ ]:
columns_of_interest10 = ['Cloud9am','Cloud3pm','Evaporation','Sunshine']

for column in columns_of_interest10:
    unique_values = df[column].unique().tolist()
    print(f"Valores únicos de la columna {column} -> {unique_values}")
Valores únicos de la columna Cloud9am -> [8.0, nan, 7.0, 1.0, 0.0, 5.0, 4.0, 2.0, 6.0, 3.0, 9.0]
Valores únicos de la columna Cloud3pm -> [nan, 2.0, 8.0, 7.0, 1.0, 5.0, 4.0, 6.0, 3.0, 0.0, 9.0]
Valores únicos de la columna Evaporation -> [nan, 12.0, 14.8, 12.6, 10.8, 11.4, 11.2, 13.0, 9.8, 14.6, 11.0, 12.8, 13.8, 16.4, 17.4, 16.0, 13.6, 8.0, 8.2, 8.6, 14.2, 15.8, 16.2, 13.4, 14.4, 11.8, 15.6, 15.2, 11.6, 9.6, 6.6, 0.6, 6.0, 3.0, 2.0, 5.2, 9.0, 10.2, 10.0, 7.4, 8.4, 9.2, 9.4, 12.4, 10.4, 7.2, 6.8, 7.6, 4.4, 6.4, 7.8, 7.0, 8.8, 6.2, 5.8, 0.2, 2.4, 1.8, 2.2, 2.8, 5.0, 5.6, 4.8, 4.2, 4.0, 3.2, 4.6, 3.4, 3.6, 0.0, 1.4, 3.8, 0.8, 2.6, 1.6, 1.2, 1.0, 5.4, 10.6, 16.8, 17.0, 20.2, 14.0, 17.2, 12.2, 15.0, 18.2, 13.2, 4.1, 1.7, 0.4, 1.9, 64.8, 32.0, 26.2, 24.6, 23.3, 15.4, 32.6, 30.4, 34.4, 18.0, 49.4, 18.8, 19.0, 18.4, 8.1, 4.9, 25.2, 24.0, 22.4, 16.6, 48.8, 56.2, 37.0, 52.4, 17.6, 6.3, 20.0, 21.4, 25.0, 17.8, 25.6, 18.6, 21.6, 35.4, 23.0, 22.0, 30.8, 11.1, 19.8, 33.2, 86.2, 65.8, 56.4, 31.2, 21.8, 5.7, 2.7, 1.3, 2.5, 3.3, 9.9, 2.3, 0.7, 2.1, 1.1, 2.9, 1.5, 3.1, 6.1, 19.6, 9.7, 10.5, 5.9, 9.3, 20.4, 12.1, 30.6, 24.2, 0.3, 47.2, 19.2, 38.4, 34.6, 23.6, 44.2, 32.2, 31.4, 34.2, 20.6, 26.8, 22.6, 23.8, 38.6, 26.4, 46.8, 42.4, 46.6, 60.2, 37.6, 36.4, 48.4, 43.6, 35.0, 50.4, 35.8, 54.0, 41.2, 32.8, 35.6, 31.0, 32.4, 19.4, 60.8, 27.4, 43.4, 27.0, 36.8, 25.4, 57.2, 28.6, 33.6, 37.4, 23.4, 43.0, 36.2, 31.6, 39.2, 25.8, 65.4, 40.4, 26.0, 21.2, 7.1, 74.8, 37.2, 28.8, 5.3, 4.7, 8.7, 3.9, 3.5, 9.5, 0.9, 30.2, 14.7, 13.1, 7.5, 8.3, 5.1, 3.7, 5.5, 18.1, 4.3, 21.0, 33.8, 4.5, 20.5, 11.9, 6.9, 7.7, 9.1, 10.9, 19.7, 10.1, 6.7, 0.5, 13.9, 12.5, 0.1, 14.5, 19.1, 17.1, 7.3, 25.1, 22.2, 27.2, 19.3, 6.5, 27.6, 11.5, 22.8, 28.4, 20.8, 39.4, 27.8, 28.2, 26.6, 33.0, 29.8, 23.2, 33.4, 28.0, 38.0, 40.0, 29.2, 29.4, 38.8, 64.4, 30.0, 24.4, 24.8, 55.4, 59.2, 145.0, 47.0, 8.9, 13.5, 8.5, 11.3, 44.0, 7.9, 44.4, 22.1, 36.6, 36.0, 34.0, 14.9, 42.6, 14.3, 10.3, 11.7, 10.7, 81.2, 63.0, 70.0, 54.8, 59.8, 72.2, 64.0, 59.6, 59.0, 42.3, 12.7, 17.7, 22.5, 15.3, 35.2, 34.5, 23.1, 42.2, 82.4, 42.0, 43.2, 62.0, 77.3, 13.3, 55.2, 58.0, 57.6, 55.6, 46.2, 55.0, 50.8, 51.0, 68.8, 51.6, 58.5, 55.8, 53.6, 25.5, 56.0, 48.0, 70.4, 59.4, 56.6, 14.1, 12.3, 15.1, 16.5, 41.8, 40.8, 50.2, 41.6, 42.8, 39.6]
Valores únicos de la columna Sunshine -> [nan, 12.3, 13.0, 13.3, 10.6, 12.2, 8.4, 0.0, 12.6, 13.2, 12.7, 12.1, 10.3, 13.1, 12.9, 11.3, 6.9, 10.9, 3.7, 5.9, 10.5, 12.4, 13.4, 13.6, 7.4, 10.0, 2.3, 6.6, 0.3, 10.7, 11.6, 10.2, 9.0, 12.0, 3.0, 7.9, 11.5, 11.2, 4.8, 5.8, 6.0, 11.1, 11.8, 11.4, 10.8, 7.8, 11.0, 5.5, 4.7, 4.2, 4.4, 6.2, 9.8, 9.9, 4.3, 8.0, 9.6, 10.4, 9.3, 8.7, 7.6, 7.5, 10.1, 6.3, 2.8, 0.7, 9.4, 9.7, 0.6, 5.1, 8.3, 4.1, 3.9, 6.8, 8.6, 2.7, 8.2, 3.1, 1.8, 0.1, 0.8, 3.4, 7.1, 5.0, 5.7, 6.1, 7.0, 2.9, 2.5, 4.6, 8.9, 9.1, 1.7, 8.1, 9.5, 1.2, 1.4, 8.8, 2.2, 3.5, 9.2, 1.9, 11.7, 11.9, 7.7, 0.9, 12.5, 2.1, 12.8, 13.7, 8.5, 0.2, 4.0, 2.4, 5.2, 0.5, 6.4, 4.5, 1.1, 2.0, 0.4, 1.5, 3.3, 6.5, 2.6, 3.8, 3.6, 3.2, 6.7, 5.4, 7.2, 4.9, 1.0, 1.6, 5.3, 7.3, 5.6, 1.3, 13.8, 13.5, 14.0, 13.9, 14.1, 14.5, 14.3, 14.2]

Recomendación: Las columnas con más de 10%, teniendo el contexto del caso, se recomienda utilizar KNNImputer o DecisionTree debido descartando por completo imputar por la moda o promedio. Esto debido a la relevancia que tendrá cada variable y más aún teniendo en cuenta el alto porcentaje de valores nulos que puede alcanzar hasta un 47%.

4 Revisión de Outliers¶

In [ ]:
df.describe()

columnas_relevantes = ['MinTemp','MaxTemp','Rainfall',
'Evaporation','Sunshine','WindGustSpeed','WindSpeed9am','WindSpeed3pm','Humidity9am',
'Humidity3pm','Pressure9am','Pressure3pm','Cloud9am','Cloud3pm','Temp9am','Temp3pm','RISK_MM']  # Asegúrate de ajustar esto según tus necesidades
df_business_understanding = df[columnas_relevantes]

# Crear un gráfico de caja para cada variable numérica por separado
for columna in df_business_understanding.columns:
    plt.figure(figsize=(8, 4))  # Ajusta el tamaño del gráfico según necesites
    sns.boxplot(x=df_business_understanding[columna], palette="Set2")
    plt.title(f'Diagrama de Caja para {columna}')
    plt.xlabel('Valores')
    plt.show()
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
In [ ]:
for columna in df_business_understanding.columns:
    q1 = df_business_understanding[columna].quantile(0.25)
    q3 = df_business_understanding[columna].quantile(0.75)
    iqr = q3 - q1
    limite_inferior = q1 - 1.5 * iqr
    limite_superior = q3 + 1.5 * iqr

    # Contar outliers
    outliers = df_business_understanding[columna][(df_business_understanding[columna] < limite_inferior) | (df_business_understanding[columna] > limite_superior)]
    cantidad_outliers = outliers.count()
    porcentaje_outliers = (cantidad_outliers / df_business_understanding.shape[0]) * 100

    # Imprimir resultados
    print(f"La cantidad de outliers en la variable {columna} es: {cantidad_outliers}")
    print(f"El porcentaje de outliers en la variable {columna} es: {round(porcentaje_outliers, 2)}%")
    print("\n")
La cantidad de outliers en la variable MinTemp es: 62
El porcentaje de outliers en la variable MinTemp es: 0.04%


La cantidad de outliers en la variable MaxTemp es: 459
El porcentaje de outliers en la variable MaxTemp es: 0.32%


La cantidad de outliers en la variable Rainfall es: 25228
El porcentaje de outliers en la variable Rainfall es: 17.74%


La cantidad de outliers en la variable Evaporation es: 1954
El porcentaje de outliers en la variable Evaporation es: 1.37%


La cantidad de outliers en la variable Sunshine es: 0
El porcentaje de outliers en la variable Sunshine es: 0.0%


La cantidad de outliers en la variable WindGustSpeed es: 3006
El porcentaje de outliers en la variable WindGustSpeed es: 2.11%


La cantidad de outliers en la variable WindSpeed9am es: 1739
El porcentaje de outliers en la variable WindSpeed9am es: 1.22%


La cantidad de outliers en la variable WindSpeed3pm es: 2458
El porcentaje de outliers en la variable WindSpeed3pm es: 1.73%


La cantidad de outliers en la variable Humidity9am es: 1419
El porcentaje de outliers en la variable Humidity9am es: 1.0%


La cantidad de outliers en la variable Humidity3pm es: 0
El porcentaje de outliers en la variable Humidity3pm es: 0.0%


La cantidad de outliers en la variable Pressure9am es: 1174
El porcentaje de outliers en la variable Pressure9am es: 0.83%


La cantidad de outliers en la variable Pressure3pm es: 906
El porcentaje de outliers en la variable Pressure3pm es: 0.64%


La cantidad de outliers en la variable Cloud9am es: 0
El porcentaje de outliers en la variable Cloud9am es: 0.0%


La cantidad de outliers en la variable Cloud3pm es: 0
El porcentaje de outliers en la variable Cloud3pm es: 0.0%


La cantidad de outliers en la variable Temp9am es: 247
El porcentaje de outliers en la variable Temp9am es: 0.17%


La cantidad de outliers en la variable Temp3pm es: 735
El porcentaje de outliers en la variable Temp3pm es: 0.52%


La cantidad de outliers en la variable RISK_MM es: 25573
El porcentaje de outliers en la variable RISK_MM es: 17.98%


Recomendaciones:

  1. Para las columnas Rainfall, RISK_MM, WindGustSpeed, WindSpeed9am, WindSpeed3pm: Dejar los datos atípicos, ya que serán importantes para predecir los futuros target preseleccionados.
  2. Evaporation, Humidity9am, Humidity3pm, Pressure9am y Pressure3pm: Se recomienda aplicar transformaciones para normalizar su distribución y reducir el impacto de valores extremadamente altos en el análisis.
  3. Para el resto de campos al ser menos al 1% podemos mantenerlos y considerar trabajarlos solo si es necesario mejorar para el modelado.

5 Distribución de datos para variables objetivo¶

5.1 RainTomorrow¶
In [ ]:
rain_tomorrow_counts = df['RainTomorrow'].value_counts()

print(rain_tomorrow_counts)
RainTomorrow
No     110316
Yes     31877
Name: count, dtype: int64
In [ ]:
rain_tomorrow_percentages = df['RainTomorrow'].value_counts(normalize=True) * 100

print("Porcentaje de registros según 'RainTomorrow':")
print(rain_tomorrow_percentages)
Porcentaje de registros según 'RainTomorrow':
RainTomorrow
No     77.581878
Yes    22.418122
Name: proportion, dtype: float64

Recomendación: Utilizar técnicas de sobremuestreo para generar registros y así equilibrar la distribución

5.2 RISK_MM¶
In [ ]:
plt.figure(figsize=(10, 6))
plt.hist(df['RISK_MM'], bins=50, edgecolor='k', alpha=0.7)
plt.title('Distribución de RISK_MM')
plt.xlabel('RISK_MM')
plt.ylabel('Frecuencia')
plt.grid(True)
plt.show()

# Boxplot
plt.figure(figsize=(10, 6))
sns.boxplot(x=df['RISK_MM'])
plt.title('Boxplot de RISK_MM')
plt.xlabel('RISK_MM')
plt.show()
No description has been provided for this image
No description has been provided for this image
In [ ]:
# Estadísticas descriptivas
risk_mm_stats = df['RISK_MM'].describe()
print("Estadísticas descriptivas de RISK_MM:")
print(risk_mm_stats)
Estadísticas descriptivas de RISK_MM:
count    142193.000000
mean          2.360682
std           8.477969
min           0.000000
25%           0.000000
50%           0.000000
75%           0.800000
max         371.000000
Name: RISK_MM, dtype: float64
In [ ]:
# Configurar el tamaño del gráfico
plt.figure(figsize=(14, 8))

# Crear un gráfico de caja para RISK_MM por Location
ax = sns.boxplot(x='Location', y='RISK_MM', data=df)

# Configurar el título y las etiquetas de los ejes
plt.title('Distribución de RISK_MM por Ubicación con Línea en 90 mm')
plt.xlabel('Ubicación')
plt.ylabel('RISK_MM')

# Rotar las etiquetas del eje x para una mejor legibilidad
plt.xticks(rotation=90)

# Añadir línea horizontal en 90 mm de RISK_MM
plt.axhline(y=90, color='purple', linestyle='-', linewidth=2, label='Línea en 90 mm')

# Añadir leyenda para la línea en 90 mm
plt.legend()

# Mostrar el gráfico
plt.show()
No description has been provided for this image
In [ ]:
count_risk_mm_high = (df['RISK_MM'] > 250).sum()
print(f"Cantidad de registros con RISK_MM > 250: {count_risk_mm_high}")
Cantidad de registros con RISK_MM > 250: 4

Análisis: Las regiones con mayor pick de RISK_MM coinciden con las regiones en las que normalmente llueve mas de acuerdo a las condiciones meteorológicas comunes de Australia y a su geografía. Esto se determinó teniendo en cuenta una linea que señala los 90mm, siendo esta la medida de riesgo máxima a la hora de preedcir la precipitación.

Recomendación: Se recomienda eliminar los registros con mas de 250 mm ya que pueden representar un riesgo en el sesgo de nuestras predicciones.

Fase 3: Data Preparation¶

Transformación, eliminación e imputación de datos¶

1. Unificación de datos nulos¶

Debido a que es probable que hayan datos nulos escritos de diferentes maneras, dejaremos todos los datos como np.nan

In [ ]:
na_values = ('np.nan','NA','NaN','nan','inf','NULL')
df = df.replace(na_values, np.nan)

2. Imputación promedio para columnas con menos del 10% de valores nulos¶

Se imputara usando el promedio o moda según sea el caso

In [ ]:
# Columnas a imputar
numeric_columns = ['MaxTemp', 'MinTemp', 'Temp9am', 'WindSpeed9am', 'WindGustSpeed', 'Rainfall', 
                   'Humidity9am', 'WindSpeed3pm', 'Temp3pm', 'Humidity3pm', 
                   'Pressure3pm', 'Pressure9am']

categorical_columns = ['RainToday', 'WindDir3pm', 'WindGustDir', 'WindDir9am']

# Imputación para columnas numéricas
numeric_imputer = SimpleImputer(strategy='mean')
df[numeric_columns] = numeric_imputer.fit_transform(df[numeric_columns])

# Imputación para columnas categóricas
categorical_imputer = SimpleImputer(strategy='most_frequent')
df[categorical_columns] = categorical_imputer.fit_transform(df[categorical_columns])

# Verificar la imputación
print(df.isnull().sum())
Date                 0
Location             0
MinTemp              0
MaxTemp              0
Rainfall             0
Evaporation      60843
Sunshine         67816
WindGustDir          0
WindGustSpeed        0
WindDir9am           0
WindDir3pm           0
WindSpeed9am         0
WindSpeed3pm         0
Humidity9am          0
Humidity3pm          0
Pressure9am          0
Pressure3pm          0
Cloud9am         53657
Cloud3pm         57094
Temp9am              0
Temp3pm              0
RainToday            0
RISK_MM              0
RainTomorrow         0
dtype: int64

3. Imputación de columnas con valores nulos mayores al 10% por KNNImputer¶

In [ ]:
# Columnas a imputar con KNNImputer
knn_columns = ['Evaporation', 'Sunshine', 'Cloud9am', 'Cloud3pm']

# Crear una copia del DataFrame para evitar la imputación en columnas no necesarias
df_knn = df[knn_columns].copy()

# KNN Imputer
knn_imputer = KNNImputer(n_neighbors=5)

# Realizar la imputación
df_knn_imputed = knn_imputer.fit_transform(df_knn)

# Convertir el resultado de nuevo a DataFrame y asignar los nombres de las columnas
df_knn_imputed = pd.DataFrame(df_knn_imputed, columns=knn_columns)

# Reemplazar las columnas originales con las columnas imputadas
df[knn_columns] = df_knn_imputed

# Verificar la imputación
print(df.isnull().sum())
Date             0
Location         0
MinTemp          0
MaxTemp          0
Rainfall         0
Evaporation      0
Sunshine         0
WindGustDir      0
WindGustSpeed    0
WindDir9am       0
WindDir3pm       0
WindSpeed9am     0
WindSpeed3pm     0
Humidity9am      0
Humidity3pm      0
Pressure9am      0
Pressure3pm      0
Cloud9am         0
Cloud3pm         0
Temp9am          0
Temp3pm          0
RainToday        0
RISK_MM          0
RainTomorrow     0
dtype: int64

Revisión de columnas con datos nulos

In [ ]:
null_counts = df.isnull().sum()
null_counts[null_counts > 0].sort_values(ascending=False)
Out[ ]:
Series([], dtype: int64)

4. Eliminación de registros con mas de 250 en RISK_MM¶

In [ ]:
# Eliminar los registros donde RISK_MM > 250
df = df[df['RISK_MM'] <= 250]

# Verificamos el tamaño del DataFrame original y el filtrado
print(f"Tamaño original del DataFrame: {df.shape[0]}")
print(f"Tamaño del DataFrame después de eliminar RISK_MM > 250: {df.shape[0]}")
Tamaño original del DataFrame: 142189
Tamaño del DataFrame después de eliminar RISK_MM > 250: 142189

5. Eliminación de la columna Date¶

In [ ]:
# df = df.drop(columns=['Date'])

Aahh se la creyó jajaja¶

5. Transformación de la columna date para facilitar su uso¶

En este caso se deció transformar las fechas solo a meses del año así podremos manejar una mayor precisión con los 12 meses del año en lugar de solo 4 tipos en las estaciones.

In [ ]:
# Convertir la columna 'Date' a datetime
df['Date'] = pd.to_datetime(df['Date'])

# Extraer solo el mes y reemplazar la columna 'Date' con el mes
df['Date'] = df['Date'].dt.month

# Imprimir el DataFrame resultante
print(df)
        Date Location  MinTemp  MaxTemp  Rainfall  Evaporation  Sunshine  \
0         12   Albury     13.4     22.9       0.6     4.560000  2.840000   
1         12   Albury      7.4     25.1       0.0     5.469824  7.624853   
2         12   Albury     12.9     25.7       0.0     4.440000  8.480000   
3         12   Albury      9.2     28.0       0.0     5.469824  7.624853   
4         12   Albury     17.5     32.3       1.0     5.880000  2.300000   
...      ...      ...      ...      ...       ...          ...       ...   
142188     6    Uluru      3.5     21.8       0.0     5.469824  7.624853   
142189     6    Uluru      2.8     23.4       0.0     5.469824  7.624853   
142190     6    Uluru      3.6     25.3       0.0     5.469824  7.624853   
142191     6    Uluru      5.4     26.9       0.0     5.469824  7.624853   
142192     6    Uluru      7.8     27.0       0.0     6.840000  9.240000   

       WindGustDir  WindGustSpeed WindDir9am  ... Humidity3pm  Pressure9am  \
0                W           44.0          W  ...        22.0       1007.7   
1              WNW           44.0        NNW  ...        25.0       1010.6   
2              WSW           46.0          W  ...        30.0       1007.6   
3               NE           24.0         SE  ...        16.0       1017.6   
4                W           41.0        ENE  ...        33.0       1010.8   
...            ...            ...        ...  ...         ...          ...   
142188           E           31.0        ESE  ...        27.0       1024.7   
142189           E           31.0         SE  ...        24.0       1024.6   
142190         NNW           22.0         SE  ...        21.0       1023.5   
142191           N           37.0         SE  ...        24.0       1021.0   
142192          SE           28.0        SSE  ...        24.0       1019.4   

        Pressure3pm  Cloud9am  Cloud3pm  Temp9am  Temp3pm  RainToday  RISK_MM  \
0            1007.1  8.000000  5.600000     16.9     21.8         No      0.0   
1            1007.8  4.437189  4.503167     17.2     24.3         No      0.0   
2            1008.7  4.600000  2.000000     21.0     23.2         No      0.0   
3            1012.8  4.437189  4.503167     18.1     26.5         No      1.0   
4            1006.0  7.000000  8.000000     17.8     29.7         No      0.2   
...             ...       ...       ...      ...      ...        ...      ...   
142188       1021.2  4.437189  4.503167      9.4     20.9         No      0.0   
142189       1020.3  4.437189  4.503167     10.1     22.4         No      0.0   
142190       1019.1  4.437189  4.503167     10.9     24.5         No      0.0   
142191       1016.8  4.437189  4.503167     12.5     26.1         No      0.0   
142192       1016.5  3.000000  2.000000     15.1     26.0         No      0.0   

        RainTomorrow  
0                 No  
1                 No  
2                 No  
3                 No  
4                 No  
...              ...  
142188            No  
142189            No  
142190            No  
142191            No  
142192            No  

[142189 rows x 24 columns]

6.1 Transformación de location a regiones basado en un estudio del clima para la ganadería¶

image.png

In [ ]:
# Diccionario de ubicaciones y climas
ubicaciones_climas = {
    "Albury": "mediterraneo",
    "BadgerysCreek": "mediterraneo",
    "Cobar": "arido_calido",
    "CoffsHarbour": "mediterraneo",
    "Moree": "mediterraneo",
    "Newcastle": "mediterraneo",
    "NorahHead": "mediterraneo",
    "NorfolkIsland": "mediterraneo",
    "Penrith": "mediterraneo",
    "Richmond": "mediterraneo",
    "Sydney": "mediterraneo",
    "SydneyAirport": "mediterraneo",
    "WaggaWagga": "semiarido_calido",
    "Williamtown": "mediterraneo",
    "Wollongong": "mediterraneo",
    "Canberra": "mediterraneo",
    "Tuggeranong": "mediterraneo",
    "MountGinini": "mediterraneo",
    "Ballarat": "mediterraneo",
    "Bendigo": "mediterraneo",
    "Sale": "mediterraneo",
    "MelbourneAirport": "mediterraneo",
    "Melbourne": "mediterraneo",
    "Mildura": "semiarido_calido",
    "Nhil": "semiarido_calido",
    "Portland": "mediterraneo",
    "Watsonia": "mediterraneo",
    "Dartmoor": "mediterraneo",
    "Brisbane": "tropical_humedo",
    "Cairns": "Sabana",
    "GoldCoast": "tropical_humedo",
    "Townsville": "Sabana",
    "Adelaide": "mediterraneo",
    "MountGambier": "mediterraneo",
    "Nuriootpa": "mediterraneo",
    "Woomera": "arido_calido",
    "Albany": "mediterraneo",
    "Witchcliffe": "mediterraneo",
    "PearceRAAF": "mediterraneo",
    "PerthAirport": "mediterraneo",
    "Perth": "mediterraneo",
    "SalmonGums": "mediterraneo",
    "Walpole": "mediterraneo",
    "Hobart": "mediterraneo",
    "Launceston": "mediterraneo",
    "AliceSprings": "arido_calido",
    "Darwin": "Sabana",
    "Katherine": "Sabana",
    "Uluru": "arido_calido"
}

# Reemplazar los valores de la columna 'ubicacion' según el diccionario
df['Location'] = df['Location'].replace(ubicaciones_climas)
# Imprimir el DataFrame resultante
print(df)
        Date      Location  MinTemp  MaxTemp  Rainfall  Evaporation  Sunshine  \
0         12  mediterraneo     13.4     22.9       0.6     4.560000  2.840000   
1         12  mediterraneo      7.4     25.1       0.0     5.469824  7.624853   
2         12  mediterraneo     12.9     25.7       0.0     4.440000  8.480000   
3         12  mediterraneo      9.2     28.0       0.0     5.469824  7.624853   
4         12  mediterraneo     17.5     32.3       1.0     5.880000  2.300000   
...      ...           ...      ...      ...       ...          ...       ...   
142188     6  arido_calido      3.5     21.8       0.0     5.469824  7.624853   
142189     6  arido_calido      2.8     23.4       0.0     5.469824  7.624853   
142190     6  arido_calido      3.6     25.3       0.0     5.469824  7.624853   
142191     6  arido_calido      5.4     26.9       0.0     5.469824  7.624853   
142192     6  arido_calido      7.8     27.0       0.0     6.840000  9.240000   

       WindGustDir  WindGustSpeed WindDir9am  ... Humidity3pm  Pressure9am  \
0                W           44.0          W  ...        22.0       1007.7   
1              WNW           44.0        NNW  ...        25.0       1010.6   
2              WSW           46.0          W  ...        30.0       1007.6   
3               NE           24.0         SE  ...        16.0       1017.6   
4                W           41.0        ENE  ...        33.0       1010.8   
...            ...            ...        ...  ...         ...          ...   
142188           E           31.0        ESE  ...        27.0       1024.7   
142189           E           31.0         SE  ...        24.0       1024.6   
142190         NNW           22.0         SE  ...        21.0       1023.5   
142191           N           37.0         SE  ...        24.0       1021.0   
142192          SE           28.0        SSE  ...        24.0       1019.4   

        Pressure3pm  Cloud9am  Cloud3pm  Temp9am  Temp3pm  RainToday  RISK_MM  \
0            1007.1  8.000000  5.600000     16.9     21.8         No      0.0   
1            1007.8  4.437189  4.503167     17.2     24.3         No      0.0   
2            1008.7  4.600000  2.000000     21.0     23.2         No      0.0   
3            1012.8  4.437189  4.503167     18.1     26.5         No      1.0   
4            1006.0  7.000000  8.000000     17.8     29.7         No      0.2   
...             ...       ...       ...      ...      ...        ...      ...   
142188       1021.2  4.437189  4.503167      9.4     20.9         No      0.0   
142189       1020.3  4.437189  4.503167     10.1     22.4         No      0.0   
142190       1019.1  4.437189  4.503167     10.9     24.5         No      0.0   
142191       1016.8  4.437189  4.503167     12.5     26.1         No      0.0   
142192       1016.5  3.000000  2.000000     15.1     26.0         No      0.0   

        RainTomorrow  
0                 No  
1                 No  
2                 No  
3                 No  
4                 No  
...              ...  
142188            No  
142189            No  
142190            No  
142191            No  
142192            No  

[142189 rows x 24 columns]

6. One Hot Encoding¶

In [ ]:
categorical_columns = ['Location','WindGustDir','WindDir9am','WindDir3pm','RainToday','RainTomorrow']

# Inicializar el OneHotEncoder
encoder = OneHotEncoder(sparse=False, handle_unknown='ignore')

# Aplicar el encoder y transformar las columnas categóricas
encoded_columns = encoder.fit_transform(df[categorical_columns])

# Crear un DataFrame con las columnas codificadas
encoded_df = pd.DataFrame(encoded_columns, columns=encoder.get_feature_names_out(categorical_columns))

# Concatenar las columnas codificadas con el DataFrame original (excluyendo las columnas originales)
df = pd.concat([df.drop(columns=categorical_columns), encoded_df], axis=1)

# Verificar la transformación
print(df.head())
c:\Python311\Lib\site-packages\sklearn\preprocessing\_encoders.py:868: FutureWarning: `sparse` was renamed to `sparse_output` in version 1.2 and will be removed in 1.4. `sparse_output` is ignored unless you leave `sparse` to its default value.
  warnings.warn(
   Date  MinTemp  MaxTemp  Rainfall  Evaporation  Sunshine  WindGustSpeed  \
0  12.0     13.4     22.9       0.6     4.560000  2.840000           44.0   
1  12.0      7.4     25.1       0.0     5.469824  7.624853           44.0   
2  12.0     12.9     25.7       0.0     4.440000  8.480000           46.0   
3  12.0      9.2     28.0       0.0     5.469824  7.624853           24.0   
4  12.0     17.5     32.3       1.0     5.880000  2.300000           41.0   

   WindSpeed9am  WindSpeed3pm  Humidity9am  ...  WindDir3pm_SSE  \
0          20.0          24.0         71.0  ...             0.0   
1           4.0          22.0         44.0  ...             0.0   
2          19.0          26.0         38.0  ...             0.0   
3          11.0           9.0         45.0  ...             0.0   
4           7.0          20.0         82.0  ...             0.0   

   WindDir3pm_SSW  WindDir3pm_SW  WindDir3pm_W  WindDir3pm_WNW  \
0             0.0            0.0           0.0             1.0   
1             0.0            0.0           0.0             0.0   
2             0.0            0.0           0.0             0.0   
3             0.0            0.0           0.0             0.0   
4             0.0            0.0           0.0             0.0   

   WindDir3pm_WSW  RainToday_No  RainToday_Yes  RainTomorrow_No  \
0             0.0           1.0            0.0              1.0   
1             1.0           1.0            0.0              1.0   
2             1.0           1.0            0.0              1.0   
3             0.0           1.0            0.0              1.0   
4             0.0           1.0            0.0              1.0   

   RainTomorrow_Yes  
0               0.0  
1               0.0  
2               0.0  
3               0.0  
4               0.0  

[5 rows x 75 columns]
In [ ]:
df.info(max_cols=300)
<class 'pandas.core.frame.DataFrame'>
Index: 142193 entries, 0 to 136880
Data columns (total 75 columns):
 #   Column                     Non-Null Count   Dtype  
---  ------                     --------------   -----  
 0   Date                       142189 non-null  float64
 1   MinTemp                    142189 non-null  float64
 2   MaxTemp                    142189 non-null  float64
 3   Rainfall                   142189 non-null  float64
 4   Evaporation                142189 non-null  float64
 5   Sunshine                   142189 non-null  float64
 6   WindGustSpeed              142189 non-null  float64
 7   WindSpeed9am               142189 non-null  float64
 8   WindSpeed3pm               142189 non-null  float64
 9   Humidity9am                142189 non-null  float64
 10  Humidity3pm                142189 non-null  float64
 11  Pressure9am                142189 non-null  float64
 12  Pressure3pm                142189 non-null  float64
 13  Cloud9am                   142189 non-null  float64
 14  Cloud3pm                   142189 non-null  float64
 15  Temp9am                    142189 non-null  float64
 16  Temp3pm                    142189 non-null  float64
 17  RISK_MM                    142189 non-null  float64
 18  Location_Sabana            142189 non-null  float64
 19  Location_arido_calido      142189 non-null  float64
 20  Location_mediterraneo      142189 non-null  float64
 21  Location_semiarido_calido  142189 non-null  float64
 22  Location_tropical_humedo   142189 non-null  float64
 23  WindGustDir_E              142189 non-null  float64
 24  WindGustDir_ENE            142189 non-null  float64
 25  WindGustDir_ESE            142189 non-null  float64
 26  WindGustDir_N              142189 non-null  float64
 27  WindGustDir_NE             142189 non-null  float64
 28  WindGustDir_NNE            142189 non-null  float64
 29  WindGustDir_NNW            142189 non-null  float64
 30  WindGustDir_NW             142189 non-null  float64
 31  WindGustDir_S              142189 non-null  float64
 32  WindGustDir_SE             142189 non-null  float64
 33  WindGustDir_SSE            142189 non-null  float64
 34  WindGustDir_SSW            142189 non-null  float64
 35  WindGustDir_SW             142189 non-null  float64
 36  WindGustDir_W              142189 non-null  float64
 37  WindGustDir_WNW            142189 non-null  float64
 38  WindGustDir_WSW            142189 non-null  float64
 39  WindDir9am_E               142189 non-null  float64
 40  WindDir9am_ENE             142189 non-null  float64
 41  WindDir9am_ESE             142189 non-null  float64
 42  WindDir9am_N               142189 non-null  float64
 43  WindDir9am_NE              142189 non-null  float64
 44  WindDir9am_NNE             142189 non-null  float64
 45  WindDir9am_NNW             142189 non-null  float64
 46  WindDir9am_NW              142189 non-null  float64
 47  WindDir9am_S               142189 non-null  float64
 48  WindDir9am_SE              142189 non-null  float64
 49  WindDir9am_SSE             142189 non-null  float64
 50  WindDir9am_SSW             142189 non-null  float64
 51  WindDir9am_SW              142189 non-null  float64
 52  WindDir9am_W               142189 non-null  float64
 53  WindDir9am_WNW             142189 non-null  float64
 54  WindDir9am_WSW             142189 non-null  float64
 55  WindDir3pm_E               142189 non-null  float64
 56  WindDir3pm_ENE             142189 non-null  float64
 57  WindDir3pm_ESE             142189 non-null  float64
 58  WindDir3pm_N               142189 non-null  float64
 59  WindDir3pm_NE              142189 non-null  float64
 60  WindDir3pm_NNE             142189 non-null  float64
 61  WindDir3pm_NNW             142189 non-null  float64
 62  WindDir3pm_NW              142189 non-null  float64
 63  WindDir3pm_S               142189 non-null  float64
 64  WindDir3pm_SE              142189 non-null  float64
 65  WindDir3pm_SSE             142189 non-null  float64
 66  WindDir3pm_SSW             142189 non-null  float64
 67  WindDir3pm_SW              142189 non-null  float64
 68  WindDir3pm_W               142189 non-null  float64
 69  WindDir3pm_WNW             142189 non-null  float64
 70  WindDir3pm_WSW             142189 non-null  float64
 71  RainToday_No               142189 non-null  float64
 72  RainToday_Yes              142189 non-null  float64
 73  RainTomorrow_No            142189 non-null  float64
 74  RainTomorrow_Yes           142189 non-null  float64
dtypes: float64(75)
memory usage: 82.4 MB

Nos quedaremos solo con RainTomorrow_1 para la futura predicción

In [ ]:
df = df.drop(columns=['RainTomorrow_No'])
In [ ]:
print(df.isnull().sum())
Date                4
MinTemp             4
MaxTemp             4
Rainfall            4
Evaporation         4
                   ..
WindDir3pm_WNW      4
WindDir3pm_WSW      4
RainToday_No        4
RainToday_Yes       4
RainTomorrow_Yes    4
Length: 74, dtype: int64
In [ ]:
print(f"Cantidad de registros antes de eliminar nulos: {len(df)}")

# Eliminar registros con al menos un campo nulo
df.dropna(inplace=True)

# Mostrar la cantidad de registros después de eliminar los nulos
print(f"Cantidad de registros después de eliminar nulos: {len(df)}")
Cantidad de registros antes de eliminar nulos: 142193
Cantidad de registros después de eliminar nulos: 142185
Cantidad de registros después de eliminar nulos: 142185

7. Generación de registros para balancear RainTomorrow¶

In [ ]:
# Definir las características (X) y la variable objetivo (y)
X = df.drop(columns=['RainTomorrow_Yes'])
y = df['RainTomorrow_Yes']

# Crear el objeto SMOTE
smote = SMOTE(random_state=42)

# Aplicar SMOTE
X_resampled, y_resampled = smote.fit_resample(X, y)

# Crear un nuevo DataFrame con los datos sobremuestreados
df_resampled = pd.DataFrame(X_resampled, columns=X.columns)
df_resampled['RainTomorrow_Yes'] = y_resampled

# Mostrar información sobre el nuevo DataFrame
print(df_resampled.info())
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 220630 entries, 0 to 220629
Data columns (total 74 columns):
 #   Column                     Non-Null Count   Dtype  
---  ------                     --------------   -----  
 0   Date                       220630 non-null  float64
 1   MinTemp                    220630 non-null  float64
 2   MaxTemp                    220630 non-null  float64
 3   Rainfall                   220630 non-null  float64
 4   Evaporation                220630 non-null  float64
 5   Sunshine                   220630 non-null  float64
 6   WindGustSpeed              220630 non-null  float64
 7   WindSpeed9am               220630 non-null  float64
 8   WindSpeed3pm               220630 non-null  float64
 9   Humidity9am                220630 non-null  float64
 10  Humidity3pm                220630 non-null  float64
 11  Pressure9am                220630 non-null  float64
 12  Pressure3pm                220630 non-null  float64
 13  Cloud9am                   220630 non-null  float64
 14  Cloud3pm                   220630 non-null  float64
 15  Temp9am                    220630 non-null  float64
 16  Temp3pm                    220630 non-null  float64
 17  RISK_MM                    220630 non-null  float64
 18  Location_Sabana            220630 non-null  float64
 19  Location_arido_calido      220630 non-null  float64
 20  Location_mediterraneo      220630 non-null  float64
 21  Location_semiarido_calido  220630 non-null  float64
 22  Location_tropical_humedo   220630 non-null  float64
 23  WindGustDir_E              220630 non-null  float64
 24  WindGustDir_ENE            220630 non-null  float64
 25  WindGustDir_ESE            220630 non-null  float64
 26  WindGustDir_N              220630 non-null  float64
 27  WindGustDir_NE             220630 non-null  float64
 28  WindGustDir_NNE            220630 non-null  float64
 29  WindGustDir_NNW            220630 non-null  float64
 30  WindGustDir_NW             220630 non-null  float64
 31  WindGustDir_S              220630 non-null  float64
 32  WindGustDir_SE             220630 non-null  float64
 33  WindGustDir_SSE            220630 non-null  float64
 34  WindGustDir_SSW            220630 non-null  float64
 35  WindGustDir_SW             220630 non-null  float64
 36  WindGustDir_W              220630 non-null  float64
 37  WindGustDir_WNW            220630 non-null  float64
 38  WindGustDir_WSW            220630 non-null  float64
 39  WindDir9am_E               220630 non-null  float64
 40  WindDir9am_ENE             220630 non-null  float64
 41  WindDir9am_ESE             220630 non-null  float64
 42  WindDir9am_N               220630 non-null  float64
 43  WindDir9am_NE              220630 non-null  float64
 44  WindDir9am_NNE             220630 non-null  float64
 45  WindDir9am_NNW             220630 non-null  float64
 46  WindDir9am_NW              220630 non-null  float64
 47  WindDir9am_S               220630 non-null  float64
 48  WindDir9am_SE              220630 non-null  float64
 49  WindDir9am_SSE             220630 non-null  float64
 50  WindDir9am_SSW             220630 non-null  float64
 51  WindDir9am_SW              220630 non-null  float64
 52  WindDir9am_W               220630 non-null  float64
 53  WindDir9am_WNW             220630 non-null  float64
 54  WindDir9am_WSW             220630 non-null  float64
 55  WindDir3pm_E               220630 non-null  float64
 56  WindDir3pm_ENE             220630 non-null  float64
 57  WindDir3pm_ESE             220630 non-null  float64
 58  WindDir3pm_N               220630 non-null  float64
 59  WindDir3pm_NE              220630 non-null  float64
 60  WindDir3pm_NNE             220630 non-null  float64
 61  WindDir3pm_NNW             220630 non-null  float64
 62  WindDir3pm_NW              220630 non-null  float64
 63  WindDir3pm_S               220630 non-null  float64
 64  WindDir3pm_SE              220630 non-null  float64
 65  WindDir3pm_SSE             220630 non-null  float64
 66  WindDir3pm_SSW             220630 non-null  float64
 67  WindDir3pm_SW              220630 non-null  float64
 68  WindDir3pm_W               220630 non-null  float64
 69  WindDir3pm_WNW             220630 non-null  float64
 70  WindDir3pm_WSW             220630 non-null  float64
 71  RainToday_No               220630 non-null  float64
 72  RainToday_Yes              220630 non-null  float64
 73  RainTomorrow_Yes           220630 non-null  float64
dtypes: float64(74)
memory usage: 124.6 MB
None
In [ ]:
df_resampled.info(max_cols=200)
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 220630 entries, 0 to 220629
Data columns (total 74 columns):
 #   Column                     Non-Null Count   Dtype  
---  ------                     --------------   -----  
 0   Date                       220630 non-null  float64
 1   MinTemp                    220630 non-null  float64
 2   MaxTemp                    220630 non-null  float64
 3   Rainfall                   220630 non-null  float64
 4   Evaporation                220630 non-null  float64
 5   Sunshine                   220630 non-null  float64
 6   WindGustSpeed              220630 non-null  float64
 7   WindSpeed9am               220630 non-null  float64
 8   WindSpeed3pm               220630 non-null  float64
 9   Humidity9am                220630 non-null  float64
 10  Humidity3pm                220630 non-null  float64
 11  Pressure9am                220630 non-null  float64
 12  Pressure3pm                220630 non-null  float64
 13  Cloud9am                   220630 non-null  float64
 14  Cloud3pm                   220630 non-null  float64
 15  Temp9am                    220630 non-null  float64
 16  Temp3pm                    220630 non-null  float64
 17  RISK_MM                    220630 non-null  float64
 18  Location_Sabana            220630 non-null  float64
 19  Location_arido_calido      220630 non-null  float64
 20  Location_mediterraneo      220630 non-null  float64
 21  Location_semiarido_calido  220630 non-null  float64
 22  Location_tropical_humedo   220630 non-null  float64
 23  WindGustDir_E              220630 non-null  float64
 24  WindGustDir_ENE            220630 non-null  float64
 25  WindGustDir_ESE            220630 non-null  float64
 26  WindGustDir_N              220630 non-null  float64
 27  WindGustDir_NE             220630 non-null  float64
 28  WindGustDir_NNE            220630 non-null  float64
 29  WindGustDir_NNW            220630 non-null  float64
 30  WindGustDir_NW             220630 non-null  float64
 31  WindGustDir_S              220630 non-null  float64
 32  WindGustDir_SE             220630 non-null  float64
 33  WindGustDir_SSE            220630 non-null  float64
 34  WindGustDir_SSW            220630 non-null  float64
 35  WindGustDir_SW             220630 non-null  float64
 36  WindGustDir_W              220630 non-null  float64
 37  WindGustDir_WNW            220630 non-null  float64
 38  WindGustDir_WSW            220630 non-null  float64
 39  WindDir9am_E               220630 non-null  float64
 40  WindDir9am_ENE             220630 non-null  float64
 41  WindDir9am_ESE             220630 non-null  float64
 42  WindDir9am_N               220630 non-null  float64
 43  WindDir9am_NE              220630 non-null  float64
 44  WindDir9am_NNE             220630 non-null  float64
 45  WindDir9am_NNW             220630 non-null  float64
 46  WindDir9am_NW              220630 non-null  float64
 47  WindDir9am_S               220630 non-null  float64
 48  WindDir9am_SE              220630 non-null  float64
 49  WindDir9am_SSE             220630 non-null  float64
 50  WindDir9am_SSW             220630 non-null  float64
 51  WindDir9am_SW              220630 non-null  float64
 52  WindDir9am_W               220630 non-null  float64
 53  WindDir9am_WNW             220630 non-null  float64
 54  WindDir9am_WSW             220630 non-null  float64
 55  WindDir3pm_E               220630 non-null  float64
 56  WindDir3pm_ENE             220630 non-null  float64
 57  WindDir3pm_ESE             220630 non-null  float64
 58  WindDir3pm_N               220630 non-null  float64
 59  WindDir3pm_NE              220630 non-null  float64
 60  WindDir3pm_NNE             220630 non-null  float64
 61  WindDir3pm_NNW             220630 non-null  float64
 62  WindDir3pm_NW              220630 non-null  float64
 63  WindDir3pm_S               220630 non-null  float64
 64  WindDir3pm_SE              220630 non-null  float64
 65  WindDir3pm_SSE             220630 non-null  float64
 66  WindDir3pm_SSW             220630 non-null  float64
 67  WindDir3pm_SW              220630 non-null  float64
 68  WindDir3pm_W               220630 non-null  float64
 69  WindDir3pm_WNW             220630 non-null  float64
 70  WindDir3pm_WSW             220630 non-null  float64
 71  RainToday_No               220630 non-null  float64
 72  RainToday_Yes              220630 non-null  float64
 73  RainTomorrow_Yes           220630 non-null  float64
dtypes: float64(74)
memory usage: 124.6 MB
In [ ]:
rain_tomorrow_counts = df_resampled['RainTomorrow_Yes'].value_counts()

print(rain_tomorrow_counts)
RainTomorrow_Yes
0.0    110315
1.0    110315
Name: count, dtype: int64
In [ ]:
rain_tomorrow_percentages = df_resampled['RainTomorrow_Yes'].value_counts(normalize=True) * 100

print("Porcentaje de registros según 'RainTomorrow_Yes':")
print(rain_tomorrow_percentages)
Porcentaje de registros según 'RainTomorrow_Yes':
RainTomorrow_Yes
0.0    50.0
1.0    50.0
Name: proportion, dtype: float64

4. Manejo de Outliers¶

4.1 Realizamos tranformaciones en las columna Evaporation, Humidity9am, Humidity3pm, Pressure9am y Pressure3pm¶
In [ ]:
df_resampled['Evaporation'] = df_resampled['Evaporation'].apply(lambda x: np.log(x + 1))  # +1 para manejar 
df_resampled['Humidity9am'] = df_resampled['Humidity9am'].apply(lambda x: np.log(x + 1))
df_resampled['Humidity3pm'] = df_resampled['Humidity3pm'].apply(lambda x: np.log(x + 1))
df_resampled['Pressure9am'] = df_resampled['Pressure9am'].apply(lambda x: np.log(x + 1))
df_resampled['Pressure3pm'] = df_resampled['Pressure3pm'].apply(lambda x: np.log(x + 1))

# Verifica los resultados tras la transformación
print(df_resampled[['Evaporation', 'Humidity9am', 'Humidity3pm', 'Pressure9am', 'Pressure3pm']].head())
   Evaporation  Humidity9am  Humidity3pm  Pressure9am  Pressure3pm
0     1.715598     4.276666     3.135494     6.916418     6.915823
1     1.867149     3.806662     3.258097     6.919289     6.916517
2     1.693779     3.663562     3.433987     6.916319     6.917409
3     1.867149     3.828641     2.833213     6.926184     6.921461
4     1.928619     4.418841     3.526361     6.919486     6.914731
In [ ]:
for columna in df_resampled.columns:
    q1 = df_resampled[columna].quantile(0.25)
    q3 = df_resampled[columna].quantile(0.75)
    iqr = q3 - q1
    limite_inferior = q1 - 1.5 * iqr
    limite_superior = q3 + 1.5 * iqr

    # Contar outliers
    outliers = df_resampled[columna][(df_resampled[columna] < limite_inferior) | (df_resampled[columna] > limite_superior)]
    cantidad_outliers = outliers.count()
    porcentaje_outliers = (cantidad_outliers / df_resampled.shape[0]) * 100

    # Imprimir resultados
    print(f"La cantidad de outliers en la variable {columna} es: {cantidad_outliers}")
    print(f"El porcentaje de outliers en la variable {columna} es: {round(porcentaje_outliers, 2)}%")
    print("\n")
La cantidad de outliers en la variable Date es: 0
El porcentaje de outliers en la variable Date es: 0.0%


La cantidad de outliers en la variable MinTemp es: 64
El porcentaje de outliers en la variable MinTemp es: 0.03%


La cantidad de outliers en la variable MaxTemp es: 733
El porcentaje de outliers en la variable MaxTemp es: 0.33%


La cantidad de outliers en la variable Rainfall es: 35712
El porcentaje de outliers en la variable Rainfall es: 16.19%


La cantidad de outliers en la variable Evaporation es: 25361
El porcentaje de outliers en la variable Evaporation es: 11.49%


La cantidad de outliers en la variable Sunshine es: 7206
El porcentaje de outliers en la variable Sunshine es: 3.27%


La cantidad de outliers en la variable WindGustSpeed es: 6180
El porcentaje de outliers en la variable WindGustSpeed es: 2.8%


La cantidad de outliers en la variable WindSpeed9am es: 2863
El porcentaje de outliers en la variable WindSpeed9am es: 1.3%


La cantidad de outliers en la variable WindSpeed3pm es: 3836
El porcentaje de outliers en la variable WindSpeed3pm es: 1.74%


La cantidad de outliers en la variable Humidity9am es: 8827
El porcentaje de outliers en la variable Humidity9am es: 4.0%


La cantidad de outliers en la variable Humidity3pm es: 10441
El porcentaje de outliers en la variable Humidity3pm es: 4.73%


La cantidad de outliers en la variable Pressure9am es: 3951
El porcentaje de outliers en la variable Pressure9am es: 1.79%


La cantidad de outliers en la variable Pressure3pm es: 3310
El porcentaje de outliers en la variable Pressure3pm es: 1.5%


La cantidad de outliers en la variable Cloud9am es: 0
El porcentaje de outliers en la variable Cloud9am es: 0.0%


La cantidad de outliers en la variable Cloud3pm es: 5110
El porcentaje de outliers en la variable Cloud3pm es: 2.32%


La cantidad de outliers en la variable Temp9am es: 353
El porcentaje de outliers en la variable Temp9am es: 0.16%


La cantidad de outliers en la variable Temp3pm es: 1369
El porcentaje de outliers en la variable Temp3pm es: 0.62%


La cantidad de outliers en la variable RISK_MM es: 35386
El porcentaje de outliers en la variable RISK_MM es: 16.04%


La cantidad de outliers en la variable Location_Sabana es: 18856
El porcentaje de outliers en la variable Location_Sabana es: 8.55%


La cantidad de outliers en la variable Location_arido_calido es: 14405
El porcentaje de outliers en la variable Location_arido_calido es: 6.53%


La cantidad de outliers en la variable Location_mediterraneo es: 53879
El porcentaje de outliers en la variable Location_mediterraneo es: 24.42%


La cantidad de outliers en la variable Location_semiarido_calido es: 12442
El porcentaje de outliers en la variable Location_semiarido_calido es: 5.64%


La cantidad de outliers en la variable Location_tropical_humedo es: 11910
El porcentaje de outliers en la variable Location_tropical_humedo es: 5.4%


La cantidad de outliers en la variable WindGustDir_E es: 15346
El porcentaje de outliers en la variable WindGustDir_E es: 6.96%


La cantidad de outliers en la variable WindGustDir_ENE es: 14061
El porcentaje de outliers en la variable WindGustDir_ENE es: 6.37%


La cantidad de outliers en la variable WindGustDir_ESE es: 12869
El porcentaje de outliers en la variable WindGustDir_ESE es: 5.83%


La cantidad de outliers en la variable WindGustDir_N es: 20210
El porcentaje de outliers en la variable WindGustDir_N es: 9.16%


La cantidad de outliers en la variable WindGustDir_NE es: 13274
El porcentaje de outliers en la variable WindGustDir_NE es: 6.02%


La cantidad de outliers en la variable WindGustDir_NNE es: 13652
El porcentaje de outliers en la variable WindGustDir_NNE es: 6.19%


La cantidad de outliers en la variable WindGustDir_NNW es: 15503
El porcentaje de outliers en la variable WindGustDir_NNW es: 7.03%


La cantidad de outliers en la variable WindGustDir_NW es: 18886
El porcentaje de outliers en la variable WindGustDir_NW es: 8.56%


La cantidad de outliers en la variable WindGustDir_S es: 18192
El porcentaje de outliers en la variable WindGustDir_S es: 8.25%


La cantidad de outliers en la variable WindGustDir_SE es: 17433
El porcentaje de outliers en la variable WindGustDir_SE es: 7.9%


La cantidad de outliers en la variable WindGustDir_SSE es: 17186
El porcentaje de outliers en la variable WindGustDir_SSE es: 7.79%


La cantidad de outliers en la variable WindGustDir_SSW es: 17406
El porcentaje de outliers en la variable WindGustDir_SSW es: 7.89%


La cantidad de outliers en la variable WindGustDir_SW es: 17160
El porcentaje de outliers en la variable WindGustDir_SW es: 7.78%


La cantidad de outliers en la variable WindGustDir_W es: 39912
El porcentaje de outliers en la variable WindGustDir_W es: 18.09%


La cantidad de outliers en la variable WindGustDir_WNW es: 18641
El porcentaje de outliers en la variable WindGustDir_WNW es: 8.45%


La cantidad de outliers en la variable WindGustDir_WSW es: 18731
El porcentaje de outliers en la variable WindGustDir_WSW es: 8.49%


La cantidad de outliers en la variable WindDir9am_E es: 14937
El porcentaje de outliers en la variable WindDir9am_E es: 6.77%


La cantidad de outliers en la variable WindDir9am_ENE es: 14192
El porcentaje de outliers en la variable WindDir9am_ENE es: 6.43%


La cantidad de outliers en la variable WindDir9am_ESE es: 12662
El porcentaje de outliers en la variable WindDir9am_ESE es: 5.74%


La cantidad de outliers en la variable WindDir9am_N es: 44940
El porcentaje de outliers en la variable WindDir9am_N es: 20.37%


La cantidad de outliers en la variable WindDir9am_NE es: 14908
El porcentaje de outliers en la variable WindDir9am_NE es: 6.76%


La cantidad de outliers en la variable WindDir9am_NNE es: 18076
El porcentaje de outliers en la variable WindDir9am_NNE es: 8.19%


La cantidad de outliers en la variable WindDir9am_NNW es: 19075
El porcentaje de outliers en la variable WindDir9am_NNW es: 8.65%


La cantidad de outliers en la variable WindDir9am_NW es: 19945
El porcentaje de outliers en la variable WindDir9am_NW es: 9.04%


La cantidad de outliers en la variable WindDir9am_S es: 16538
El porcentaje de outliers en la variable WindDir9am_S es: 7.5%


La cantidad de outliers en la variable WindDir9am_SE es: 16146
El porcentaje de outliers en la variable WindDir9am_SE es: 7.32%


La cantidad de outliers en la variable WindDir9am_SSE es: 16304
El porcentaje de outliers en la variable WindDir9am_SSE es: 7.39%


La cantidad de outliers en la variable WindDir9am_SSW es: 15262
El porcentaje de outliers en la variable WindDir9am_SSW es: 6.92%


La cantidad de outliers en la variable WindDir9am_SW es: 17131
El porcentaje de outliers en la variable WindDir9am_SW es: 7.76%


La cantidad de outliers en la variable WindDir9am_W es: 18173
El porcentaje de outliers en la variable WindDir9am_W es: 8.24%


La cantidad de outliers en la variable WindDir9am_WNW es: 16502
El porcentaje de outliers en la variable WindDir9am_WNW es: 7.48%


La cantidad de outliers en la variable WindDir9am_WSW es: 14765
El porcentaje de outliers en la variable WindDir9am_WSW es: 6.69%


La cantidad de outliers en la variable WindDir3pm_E es: 14984
El porcentaje de outliers en la variable WindDir3pm_E es: 6.79%


La cantidad de outliers en la variable WindDir3pm_ENE es: 14243
El porcentaje de outliers en la variable WindDir3pm_ENE es: 6.46%


La cantidad de outliers en la variable WindDir3pm_ESE es: 14937
El porcentaje de outliers en la variable WindDir3pm_ESE es: 6.77%


La cantidad de outliers en la variable WindDir3pm_N es: 19677
El porcentaje de outliers en la variable WindDir3pm_N es: 8.92%


La cantidad de outliers en la variable WindDir3pm_NE es: 15486
El porcentaje de outliers en la variable WindDir3pm_NE es: 7.02%


La cantidad de outliers en la variable WindDir3pm_NNE es: 13890
El porcentaje de outliers en la variable WindDir3pm_NNE es: 6.3%


La cantidad de outliers en la variable WindDir3pm_NNW es: 17740
El porcentaje de outliers en la variable WindDir3pm_NNW es: 8.04%


La cantidad de outliers en la variable WindDir3pm_NW es: 19972
El porcentaje de outliers en la variable WindDir3pm_NW es: 9.05%


La cantidad de outliers en la variable WindDir3pm_S es: 19146
El porcentaje de outliers en la variable WindDir3pm_S es: 8.68%


La cantidad de outliers en la variable WindDir3pm_SE es: 27923
El porcentaje de outliers en la variable WindDir3pm_SE es: 12.66%


La cantidad de outliers en la variable WindDir3pm_SSE es: 17359
El porcentaje de outliers en la variable WindDir3pm_SSE es: 7.87%


La cantidad de outliers en la variable WindDir3pm_SSW es: 16280
El porcentaje de outliers en la variable WindDir3pm_SSW es: 7.38%


La cantidad de outliers en la variable WindDir3pm_SW es: 17701
El porcentaje de outliers en la variable WindDir3pm_SW es: 8.02%


La cantidad de outliers en la variable WindDir3pm_W es: 21530
El porcentaje de outliers en la variable WindDir3pm_W es: 9.76%


La cantidad de outliers en la variable WindDir3pm_WNW es: 19964
El porcentaje de outliers en la variable WindDir3pm_WNW es: 9.05%


La cantidad de outliers en la variable WindDir3pm_WSW es: 19106
El porcentaje de outliers en la variable WindDir3pm_WSW es: 8.66%


La cantidad de outliers en la variable RainToday_No es: 0
El porcentaje de outliers en la variable RainToday_No es: 0.0%


La cantidad de outliers en la variable RainToday_Yes es: 0
El porcentaje de outliers en la variable RainToday_Yes es: 0.0%


La cantidad de outliers en la variable RainTomorrow_Yes es: 0
El porcentaje de outliers en la variable RainTomorrow_Yes es: 0.0%


5. Revisión final luego de Data Preparation¶

6.1 Cantidad de nulos¶
In [ ]:
print(f'Cantidad total de nulos -> {df.isna().sum().sum()}')
Cantidad total de nulos -> 0
6.2 Outliers finales¶
In [ ]:
df.describe()

columnas_relevantes = ['MinTemp','MaxTemp','Rainfall',
'Evaporation','Sunshine','WindGustSpeed','WindSpeed9am','WindSpeed3pm','Humidity9am',
'Humidity3pm','Pressure9am','Pressure3pm','Cloud9am','Cloud3pm','Temp9am','Temp3pm','RISK_MM']  # Asegúrate de ajustar esto según tus necesidades
df_business_understanding = df[columnas_relevantes]

# Crear un gráfico de caja para cada variable numérica por separado
for columna in df_business_understanding.columns:
    plt.figure(figsize=(8, 4))  # Ajusta el tamaño del gráfico según necesites
    sns.boxplot(x=df_business_understanding[columna], palette="Set2")
    plt.title(f'Diagrama de Caja para {columna}')
    plt.xlabel('Valores')
    plt.show()
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image

7. DataSet Limpio¶

In [ ]:
df.head()
Out[ ]:
Date MinTemp MaxTemp Rainfall Evaporation Sunshine WindGustSpeed WindSpeed9am WindSpeed3pm Humidity9am ... WindDir3pm_SE WindDir3pm_SSE WindDir3pm_SSW WindDir3pm_SW WindDir3pm_W WindDir3pm_WNW WindDir3pm_WSW RainToday_No RainToday_Yes RainTomorrow_Yes
0 12.0 13.4 22.9 0.6 4.560000 2.840000 44.0 20.0 24.0 71.0 ... 0.0 0.0 0.0 0.0 0.0 1.0 0.0 1.0 0.0 0.0
1 12.0 7.4 25.1 0.0 5.469824 7.624853 44.0 4.0 22.0 44.0 ... 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 0.0 0.0
2 12.0 12.9 25.7 0.0 4.440000 8.480000 46.0 19.0 26.0 38.0 ... 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 0.0 0.0
3 12.0 9.2 28.0 0.0 5.469824 7.624853 24.0 11.0 9.0 45.0 ... 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0
4 12.0 17.5 32.3 1.0 5.880000 2.300000 41.0 7.0 20.0 82.0 ... 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0

5 rows × 74 columns

In [ ]:
df.info(max_cols=200)
<class 'pandas.core.frame.DataFrame'>
Index: 142185 entries, 0 to 142188
Data columns (total 74 columns):
 #   Column                     Non-Null Count   Dtype  
---  ------                     --------------   -----  
 0   Date                       142185 non-null  float64
 1   MinTemp                    142185 non-null  float64
 2   MaxTemp                    142185 non-null  float64
 3   Rainfall                   142185 non-null  float64
 4   Evaporation                142185 non-null  float64
 5   Sunshine                   142185 non-null  float64
 6   WindGustSpeed              142185 non-null  float64
 7   WindSpeed9am               142185 non-null  float64
 8   WindSpeed3pm               142185 non-null  float64
 9   Humidity9am                142185 non-null  float64
 10  Humidity3pm                142185 non-null  float64
 11  Pressure9am                142185 non-null  float64
 12  Pressure3pm                142185 non-null  float64
 13  Cloud9am                   142185 non-null  float64
 14  Cloud3pm                   142185 non-null  float64
 15  Temp9am                    142185 non-null  float64
 16  Temp3pm                    142185 non-null  float64
 17  RISK_MM                    142185 non-null  float64
 18  Location_Sabana            142185 non-null  float64
 19  Location_arido_calido      142185 non-null  float64
 20  Location_mediterraneo      142185 non-null  float64
 21  Location_semiarido_calido  142185 non-null  float64
 22  Location_tropical_humedo   142185 non-null  float64
 23  WindGustDir_E              142185 non-null  float64
 24  WindGustDir_ENE            142185 non-null  float64
 25  WindGustDir_ESE            142185 non-null  float64
 26  WindGustDir_N              142185 non-null  float64
 27  WindGustDir_NE             142185 non-null  float64
 28  WindGustDir_NNE            142185 non-null  float64
 29  WindGustDir_NNW            142185 non-null  float64
 30  WindGustDir_NW             142185 non-null  float64
 31  WindGustDir_S              142185 non-null  float64
 32  WindGustDir_SE             142185 non-null  float64
 33  WindGustDir_SSE            142185 non-null  float64
 34  WindGustDir_SSW            142185 non-null  float64
 35  WindGustDir_SW             142185 non-null  float64
 36  WindGustDir_W              142185 non-null  float64
 37  WindGustDir_WNW            142185 non-null  float64
 38  WindGustDir_WSW            142185 non-null  float64
 39  WindDir9am_E               142185 non-null  float64
 40  WindDir9am_ENE             142185 non-null  float64
 41  WindDir9am_ESE             142185 non-null  float64
 42  WindDir9am_N               142185 non-null  float64
 43  WindDir9am_NE              142185 non-null  float64
 44  WindDir9am_NNE             142185 non-null  float64
 45  WindDir9am_NNW             142185 non-null  float64
 46  WindDir9am_NW              142185 non-null  float64
 47  WindDir9am_S               142185 non-null  float64
 48  WindDir9am_SE              142185 non-null  float64
 49  WindDir9am_SSE             142185 non-null  float64
 50  WindDir9am_SSW             142185 non-null  float64
 51  WindDir9am_SW              142185 non-null  float64
 52  WindDir9am_W               142185 non-null  float64
 53  WindDir9am_WNW             142185 non-null  float64
 54  WindDir9am_WSW             142185 non-null  float64
 55  WindDir3pm_E               142185 non-null  float64
 56  WindDir3pm_ENE             142185 non-null  float64
 57  WindDir3pm_ESE             142185 non-null  float64
 58  WindDir3pm_N               142185 non-null  float64
 59  WindDir3pm_NE              142185 non-null  float64
 60  WindDir3pm_NNE             142185 non-null  float64
 61  WindDir3pm_NNW             142185 non-null  float64
 62  WindDir3pm_NW              142185 non-null  float64
 63  WindDir3pm_S               142185 non-null  float64
 64  WindDir3pm_SE              142185 non-null  float64
 65  WindDir3pm_SSE             142185 non-null  float64
 66  WindDir3pm_SSW             142185 non-null  float64
 67  WindDir3pm_SW              142185 non-null  float64
 68  WindDir3pm_W               142185 non-null  float64
 69  WindDir3pm_WNW             142185 non-null  float64
 70  WindDir3pm_WSW             142185 non-null  float64
 71  RainToday_No               142185 non-null  float64
 72  RainToday_Yes              142185 non-null  float64
 73  RainTomorrow_Yes           142185 non-null  float64
dtypes: float64(74)
memory usage: 81.4 MB

Fase 4: Modeling¶

Regresión¶

Para nuestra predicción hemos definido la variable objecto RISK_MM

In [ ]:
df_regresionTotal = df_resampled[['MinTemp','MaxTemp','Rainfall','Evaporation','Sunshine','WindGustSpeed','WindSpeed9am','WindSpeed3pm',
'Humidity9am','Humidity3pm','Pressure9am','Pressure3pm','Cloud9am','Cloud3pm','Temp9am','Temp3pm','RISK_MM',
"Location_Sabana","Location_arido_calido","Location_mediterraneo","Location_semiarido_calido","Location_tropical_humedo",
'WindGustDir_E','WindGustDir_ENE','WindGustDir_ESE','WindGustDir_N',
'WindGustDir_NE','WindGustDir_NNE','WindGustDir_NNW','WindGustDir_NW','WindGustDir_S','WindGustDir_SE','WindGustDir_SSE',
'WindGustDir_SSW','WindGustDir_SW','WindGustDir_W','WindGustDir_WNW','WindGustDir_WSW','WindDir9am_E','WindDir9am_ENE',
'WindDir9am_ESE','WindDir9am_N','WindDir9am_NE','WindDir9am_NNE','WindDir9am_NNW','WindDir9am_NW','WindDir9am_S',
'WindDir9am_SE','WindDir9am_SSE','WindDir9am_SSW','WindDir9am_SW','WindDir9am_W','WindDir9am_WNW','WindDir9am_WSW',
'WindDir3pm_E','WindDir3pm_ENE','WindDir3pm_ESE','WindDir3pm_N','WindDir3pm_NE','WindDir3pm_NNE','WindDir3pm_NNW',
'WindDir3pm_NW','WindDir3pm_S','WindDir3pm_SE','WindDir3pm_SSE','WindDir3pm_SSW','WindDir3pm_SW','WindDir3pm_W',
'WindDir3pm_WNW','WindDir3pm_WSW','RainToday_No','RainToday_Yes','RainTomorrow_Yes', 'Date']]
corr = df_regresionTotal.corr()
sns.heatmap(corr, annot=True, linewidths=.9)
Out[ ]:
<Axes: >
No description has been provided for this image

Top 20 Correlación en RainTomorrow_Yes

In [ ]:
# Calculamos la matriz de correlación
corr_matrix = df_resampled.corr()

# Usamos solo la parte superior de la matriz de correlación
upper_triangle = corr_matrix.where(np.triu(np.ones(corr_matrix.shape), k=1).astype(bool))

# Aplanamos la matriz y convertimos a un DataFrame para facilitar la manipulación
corr_unstacked = upper_triangle.unstack().reset_index()
corr_unstacked.columns = ['Variable1', 'Variable2', 'Correlation']

# Filtramos para conservar solo las filas que incluyen 'RainTomorrow_Yes'
corr_with_risk_mm = corr_unstacked[(corr_unstacked['Variable1'] == 'RainTomorrow_Yes') | (corr_unstacked['Variable2'] == 'RainTomorrow_Yes')]

# Ordenamos por el valor absoluto de la correlación, de mayor a menor
corr_with_risk_mm['AbsCorrelation'] = corr_with_risk_mm['Correlation'].abs()
top_correlations = corr_with_risk_mm.sort_values(by='AbsCorrelation', ascending=False)

# Seleccionamos las 20 correlaciones más fuertes
top_20_correlations = top_correlations.head(30)

# Imprimimos las 20 mejores correlaciones
print(top_20_correlations[['Variable1', 'Variable2', 'Correlation']])
             Variable1                  Variable2  Correlation
5474  RainTomorrow_Yes              RainToday_Yes     0.347714
5473  RainTomorrow_Yes               RainToday_No    -0.347714
5412  RainTomorrow_Yes                Humidity3pm     0.247677
5411  RainTomorrow_Yes                Humidity9am     0.189232
5419  RainTomorrow_Yes                    RISK_MM     0.184053
5416  RainTomorrow_Yes                   Cloud3pm     0.181727
5407  RainTomorrow_Yes                   Sunshine    -0.176238
5415  RainTomorrow_Yes                   Cloud9am     0.152351
5421  RainTomorrow_Yes      Location_arido_calido    -0.128704
5418  RainTomorrow_Yes                    Temp3pm    -0.111842
5404  RainTomorrow_Yes                    MaxTemp    -0.108034
5405  RainTomorrow_Yes                   Rainfall     0.102220
5406  RainTomorrow_Yes                Evaporation    -0.100966
5422  RainTomorrow_Yes      Location_mediterraneo     0.085279
5414  RainTomorrow_Yes                Pressure3pm    -0.083013
5413  RainTomorrow_Yes                Pressure9am    -0.076489
5441  RainTomorrow_Yes               WindDir9am_E    -0.068848
5425  RainTomorrow_Yes              WindGustDir_E    -0.063393
5443  RainTomorrow_Yes             WindDir9am_ESE    -0.061130
5423  RainTomorrow_Yes  Location_semiarido_calido    -0.060909
5447  RainTomorrow_Yes             WindDir9am_NNW     0.060078
5450  RainTomorrow_Yes              WindDir9am_SE    -0.051194
5408  RainTomorrow_Yes              WindGustSpeed     0.049632
5426  RainTomorrow_Yes            WindGustDir_ENE    -0.048718
5438  RainTomorrow_Yes              WindGustDir_W     0.047220
5464  RainTomorrow_Yes              WindDir3pm_NW     0.046740
5432  RainTomorrow_Yes             WindGustDir_NW     0.046519
5427  RainTomorrow_Yes            WindGustDir_ESE    -0.046049
5459  RainTomorrow_Yes             WindDir3pm_ESE    -0.045247
5448  RainTomorrow_Yes              WindDir9am_NW     0.044698
C:\Users\nicol\AppData\Local\Temp\ipykernel_7508\489232418.py:15: SettingWithCopyWarning: 
A value is trying to be set on a copy of a slice from a DataFrame.
Try using .loc[row_indexer,col_indexer] = value instead

See the caveats in the documentation: https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy
  corr_with_risk_mm['AbsCorrelation'] = corr_with_risk_mm['Correlation'].abs()

RainTomorrow_Yes:
'RainToday_Yes','Humidity3pm','Humidity9am','RISK_MM','Cloud3pm','Sunshine','Cloud9am','Temp3pm','MaxTemp','Rainfall','Evaporation','Pressure3pm','Pressure9am'

Top 20 Correlación en RISK_MM

In [ ]:
# Calculamos la matriz de correlación
corr_matrix = df_resampled.corr()

# Usamos solo la parte superior de la matriz de correlación
upper_triangle = corr_matrix.where(np.triu(np.ones(corr_matrix.shape), k=1).astype(bool))

# Aplanamos la matriz y convertimos a un DataFrame para facilitar la manipulación
corr_unstacked = upper_triangle.unstack().reset_index()
corr_unstacked.columns = ['Variable1', 'Variable2', 'Correlation']

# Filtramos para conservar solo las filas que incluyen 'RISK_MM'
corr_with_risk_mm = corr_unstacked[(corr_unstacked['Variable1'] == 'RISK_MM') | (corr_unstacked['Variable2'] == 'RISK_MM')]

# Ordenamos por el valor absoluto de la correlación, de mayor a menor
corr_with_risk_mm['AbsCorrelation'] = corr_with_risk_mm['Correlation'].abs()
top_correlations_risk_mm = corr_with_risk_mm.sort_values(by='AbsCorrelation', ascending=False)

# Seleccionamos las 20 correlaciones más fuertes
top_20_correlations_risk_mm = top_correlations_risk_mm.head(30)

# Imprimimos las 20 mejores correlaciones
print(top_20_correlations_risk_mm[['Variable1', 'Variable2', 'Correlation']])
                      Variable1      Variable2  Correlation
5345              RainToday_Yes        RISK_MM     0.365370
5271               RainToday_No        RISK_MM    -0.365370
1261                    RISK_MM       Rainfall     0.308477
1263                    RISK_MM       Sunshine    -0.269812
1268                    RISK_MM    Humidity3pm     0.264688
1272                    RISK_MM       Cloud3pm     0.227069
1271                    RISK_MM       Cloud9am     0.195392
5419           RainTomorrow_Yes        RISK_MM     0.184053
1267                    RISK_MM    Humidity9am     0.167888
1264                    RISK_MM  WindGustSpeed     0.163198
1269                    RISK_MM    Pressure9am    -0.162409
1270                    RISK_MM    Pressure3pm    -0.161860
1259                    RISK_MM        MinTemp     0.148224
1349            Location_Sabana        RISK_MM     0.085550
1265                    RISK_MM   WindSpeed9am     0.076263
1273                    RISK_MM        Temp9am     0.067447
1274                    RISK_MM        Temp3pm    -0.059104
1258                    RISK_MM           Date    -0.056000
1423      Location_arido_calido        RISK_MM    -0.048795
1266                    RISK_MM   WindSpeed3pm     0.047342
3125               WindDir9am_N        RISK_MM    -0.040698
3791              WindDir9am_SW        RISK_MM     0.038771
2311              WindGustDir_S        RISK_MM     0.037951
1260                    RISK_MM        MaxTemp    -0.036772
1571  Location_semiarido_calido        RISK_MM    -0.033903
3717             WindDir9am_SSW        RISK_MM     0.032000
4901             WindDir3pm_SSW        RISK_MM     0.031511
3273             WindDir9am_NNE        RISK_MM    -0.029205
3495               WindDir9am_S        RISK_MM     0.028584
1941              WindGustDir_N        RISK_MM    -0.023572
C:\Users\nicol\AppData\Local\Temp\ipykernel_7508\1168011706.py:15: SettingWithCopyWarning: 
A value is trying to be set on a copy of a slice from a DataFrame.
Try using .loc[row_indexer,col_indexer] = value instead

See the caveats in the documentation: https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy
  corr_with_risk_mm['AbsCorrelation'] = corr_with_risk_mm['Correlation'].abs()

RISK_MM:
'RainToday_Yes','Rainfall','Sunshine','Humidity3pm','Cloud3pm','Cloud9am','RainTomorrow_Yes','Humidity9am','WindGustSpeed','Pressure9am','Pressure3pm','MinTemp','WindSpeed9am','Temp9am','Temp3pm'

Se agregan la columna location y date¶
In [ ]:
df_regresion = df_resampled[['RainToday_Yes','Rainfall','Sunshine','Humidity3pm','Cloud3pm','Cloud9am','RainTomorrow_Yes','Humidity9am','WindGustSpeed','Pressure9am','Pressure3pm','MinTemp','WindSpeed9am','Temp9am','Temp3pm',"Location_Sabana","Location_arido_calido","Location_mediterraneo","Location_semiarido_calido","Location_tropical_humedo", 'Date']]
corr = df_regresion.corr()
plt.figure(figsize=(12, 10))
sns.heatmap(corr, annot=True, linewidths=.9)
plt.show()
No description has been provided for this image

Target seleccionado : RainTomorrow_Yes¶

Separamos datos de entrenamiento y testeo¶

In [ ]:
from sklearn.model_selection import train_test_split


# separar el dataframe en train y test con un 80% para train y 20% para test y random_state=42 y stratify=df['CUPO_L1']
X_train_reg, X_test_reg, y_train_reg, y_test_reg = train_test_split(df_regresion.drop(['RainTomorrow_Yes'], axis=1), df_regresion['RainTomorrow_Yes'], test_size=0.2, random_state=42)

Modelos sin hiperparámetros¶

Realizaremos un entrenamiento previo sin hiperparámetros para tener una vista preliminar del posible mejor modelo, los modelos seleccionados serán:

  • DecisionTreeRegressor
  • RandomForestRegressor
  • GradientBoostingRegressor
  • SVR
  • KNeighborsRegressor
  • SGDRegressor
In [ ]:
# importar todos los modelos de regresion de sklearn

from sklearn.tree import DecisionTreeRegressor
from sklearn.ensemble import RandomForestRegressor
from sklearn.ensemble import GradientBoostingRegressor
from sklearn.neighbors import KNeighborsRegressor
from sklearn.linear_model import SGDRegressor

Modelos sin hiperparámetros¶

In [ ]:
# inicializar los modelos de regresion con los parametros por defecto


dtR = DecisionTreeRegressor()
rfR = RandomForestRegressor()
gbR = GradientBoostingRegressor()
knnR = KNeighborsRegressor()
sgdR = SGDRegressor()

Entrenamiento de los modelos¶

In [ ]:
# entrenar los modelos de regresion con los datos de train

dtR.fit(X_train_reg, y_train_reg)
rfR.fit(X_train_reg, y_train_reg)
gbR.fit(X_train_reg, y_train_reg)
knnR.fit(X_train_reg, y_train_reg)
sgdR.fit(X_train_reg, y_train_reg)


# generar una lista con todos los modelos de regresion
models = [dtR, rfR, gbR, knnR, sgdR]

Vista del R² y Raíz del error cuadrática medio¶

In [ ]:
# for que recorra la lista de modelos y que imprima el MAE, MSE y RMSE, R2 de cada modelo
from sklearn.metrics import mean_absolute_error, mean_squared_error, r2_score
i = 1
for model in models:
    y_pred_reg = model.predict(X_test_reg)
    print(f'{i}° Modelo de Clasificación -> {model}\n')
    print('-'*100)
    print(f'El MSE del modelo es {mean_squared_error(y_test_reg, y_pred_reg):.3f}')
    print(f'El RMSE del modelo es {np.sqrt(mean_squared_error(y_test_reg, y_pred_reg)):.3f}')
    print(f'El R² del modelo es {r2_score(y_test_reg, y_pred_reg):.2f}\n')
    print('-'*100,'\n')
    i += 1
1° Modelo de Clasificación -> DecisionTreeRegressor()

----------------------------------------------------------------------------------------------------
El MSE del modelo es 0.205
El RMSE del modelo es 0.453
El R² del modelo es 0.18

---------------------------------------------------------------------------------------------------- 

2° Modelo de Clasificación -> RandomForestRegressor()

----------------------------------------------------------------------------------------------------
El MSE del modelo es 0.100
El RMSE del modelo es 0.316
El R² del modelo es 0.60

---------------------------------------------------------------------------------------------------- 

3° Modelo de Clasificación -> GradientBoostingRegressor()

----------------------------------------------------------------------------------------------------
El MSE del modelo es 0.136
El RMSE del modelo es 0.368
El R² del modelo es 0.46

---------------------------------------------------------------------------------------------------- 

4° Modelo de Clasificación -> KNeighborsRegressor()

----------------------------------------------------------------------------------------------------
El MSE del modelo es 0.195
El RMSE del modelo es 0.442
El R² del modelo es 0.22

---------------------------------------------------------------------------------------------------- 

5° Modelo de Clasificación -> SGDRegressor()

----------------------------------------------------------------------------------------------------
El MSE del modelo es 1052419330.356
El RMSE del modelo es 32441.013
El R² del modelo es -4209684593.47

---------------------------------------------------------------------------------------------------- 

Entrenamiento de Modelos con hiperparámetros¶

GradientBoostingRegressor¶

GradientBoostingRegressor V1¶
In [ ]:
gbV1 = GradientBoostingRegressor( learning_rate=0.1, n_estimators=100, max_depth=3, tol=2, random_state=42)
gbV1.fit(X_train_reg, y_train_reg)
Out[ ]:
GradientBoostingRegressor(random_state=42, tol=2)
In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook.
On GitHub, the HTML representation is unable to render, please try loading this page with nbviewer.org.
GradientBoostingRegressor(random_state=42, tol=2)
GradientBoostingRegressor V2¶
In [ ]:
gbV2 = GradientBoostingRegressor(
    learning_rate=0.1, n_estimators=500, max_depth=3, tol=2, random_state=42)
gbV2.fit(X_train_reg, y_train_reg)
Out[ ]:
GradientBoostingRegressor(n_estimators=500, random_state=42, tol=2)
In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook.
On GitHub, the HTML representation is unable to render, please try loading this page with nbviewer.org.
GradientBoostingRegressor(n_estimators=500, random_state=42, tol=2)
GradientBoostingRegressor V3¶
In [ ]:
gbV3 = GradientBoostingRegressor(
    learning_rate=0.1, n_estimators=100, max_depth=30, tol=2, random_state=42)
gbV3.fit(X_train_reg, y_train_reg)
Out[ ]:
GradientBoostingRegressor(max_depth=30, random_state=42, tol=2)
In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook.
On GitHub, the HTML representation is unable to render, please try loading this page with nbviewer.org.
GradientBoostingRegressor(max_depth=30, random_state=42, tol=2)
GradientBoostingRegressor V4¶
In [ ]:
gbV4 = GradientBoostingRegressor(learning_rate=0.4, n_estimators=3, max_depth=300, tol=1e-2, random_state=42)
gbV4.fit(X_train_reg, y_train_reg)
Out[ ]:
GradientBoostingRegressor(learning_rate=0.4, max_depth=300, n_estimators=3,
                          random_state=42, tol=0.01)
In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook.
On GitHub, the HTML representation is unable to render, please try loading this page with nbviewer.org.
GradientBoostingRegressor(learning_rate=0.4, max_depth=300, n_estimators=3,
                          random_state=42, tol=0.01)
GradientBoostingRegressor V5¶
In [ ]:
gbV5 = GradientBoostingRegressor( learning_rate=0.4, n_estimators=1, max_depth=3000, tol=1e-2, random_state=42)
gbV5.fit(X_train_reg, y_train_reg)
Out[ ]:
GradientBoostingRegressor(learning_rate=0.4, max_depth=3000, n_estimators=1,
                          random_state=42, tol=0.01)
In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook.
On GitHub, the HTML representation is unable to render, please try loading this page with nbviewer.org.
GradientBoostingRegressor(learning_rate=0.4, max_depth=3000, n_estimators=1,
                          random_state=42, tol=0.01)
GradientBoostingRegressor V6¶
Revisión de R² y RMSE de las 6 versiones de GradientBoostingRegressor¶
In [ ]:
models = [gbV1, gbV2, gbV3, gbV4, gbV5]
i = 1
for model in models:
    y_pred_reg = model.predict(X_test_reg)
    print(f'{i}° Modelo de Clasificación -> {model}\n')
    print('-'*100)
    print(
        f'El MSE del modelo es {mean_squared_error(y_test_reg, y_pred_reg):.3f}')
    print(f'El RMSE del modelo es {np.sqrt(mean_squared_error(y_test_reg, y_pred_reg)):.3f}')
    print(f'El R² del modelo es {r2_score(y_test_reg, y_pred_reg):.2f}\n')
    print('-'*100, '\n')
    i += 1
1° Modelo de Clasificación -> GradientBoostingRegressor(random_state=42, tol=2)

----------------------------------------------------------------------------------------------------
El MSE del modelo es 0.136
El RMSE del modelo es 0.368
El R² del modelo es 0.46

---------------------------------------------------------------------------------------------------- 

2° Modelo de Clasificación -> GradientBoostingRegressor(n_estimators=500, random_state=42, tol=2)

----------------------------------------------------------------------------------------------------
El MSE del modelo es 0.112
El RMSE del modelo es 0.335
El R² del modelo es 0.55

---------------------------------------------------------------------------------------------------- 

3° Modelo de Clasificación -> GradientBoostingRegressor(max_depth=30, random_state=42, tol=2)

----------------------------------------------------------------------------------------------------
El MSE del modelo es 0.147
El RMSE del modelo es 0.383
El R² del modelo es 0.41

---------------------------------------------------------------------------------------------------- 

4° Modelo de Clasificación -> GradientBoostingRegressor(learning_rate=0.4, max_depth=300, n_estimators=3,
                          random_state=42, tol=0.01)

----------------------------------------------------------------------------------------------------
El MSE del modelo es 0.161
El RMSE del modelo es 0.402
El R² del modelo es 0.35

---------------------------------------------------------------------------------------------------- 

5° Modelo de Clasificación -> GradientBoostingRegressor(learning_rate=0.4, max_depth=3000, n_estimators=1,
                          random_state=42, tol=0.01)

----------------------------------------------------------------------------------------------------
El MSE del modelo es 0.171
El RMSE del modelo es 0.414
El R² del modelo es 0.32

---------------------------------------------------------------------------------------------------- 

DecisionTreeRegressor¶

In [ ]:
dtrV1 = DecisionTreeRegressor(
    min_samples_split=5, min_samples_leaf=5, random_state=42)

dtrV1.fit(X_train_reg, y_train_reg)
Out[ ]:
DecisionTreeRegressor(min_samples_leaf=5, min_samples_split=5, random_state=42)
In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook.
On GitHub, the HTML representation is unable to render, please try loading this page with nbviewer.org.
DecisionTreeRegressor(min_samples_leaf=5, min_samples_split=5, random_state=42)

RandomForestRegressor¶

RandomForestRegressor V1¶
In [ ]:
rfRV1 = RandomForestRegressor(min_samples_split=5, min_samples_leaf=5, random_state=42,
                           bootstrap=True, max_samples=0.8, n_estimators=3, max_depth=40)

rfRV1.fit(X_train_reg, y_train_reg)
Out[ ]:
RandomForestRegressor(max_depth=40, max_samples=0.8, min_samples_leaf=5,
                      min_samples_split=5, n_estimators=3, random_state=42)
In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook.
On GitHub, the HTML representation is unable to render, please try loading this page with nbviewer.org.
RandomForestRegressor(max_depth=40, max_samples=0.8, min_samples_leaf=5,
                      min_samples_split=5, n_estimators=3, random_state=42)
RandomForestRegressor V2¶
In [ ]:
rfRV2 = RandomForestRegressor(min_samples_split=20, min_samples_leaf=20, random_state=42,
                           bootstrap=True, max_samples=0.8, n_estimators=12, max_depth=40)

rfRV2.fit(X_train_reg, y_train_reg)
Out[ ]:
RandomForestRegressor(max_depth=40, max_samples=0.8, min_samples_leaf=20,
                      min_samples_split=20, n_estimators=12, random_state=42)
In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook.
On GitHub, the HTML representation is unable to render, please try loading this page with nbviewer.org.
RandomForestRegressor(max_depth=40, max_samples=0.8, min_samples_leaf=20,
                      min_samples_split=20, n_estimators=12, random_state=42)

KNeighborsRegressor¶

In [ ]:
knnRV1 = KNeighborsRegressor(
    n_neighbors=2000, weights='distance', algorithm='auto', leaf_size=40, p=2)

knnRV1.fit(X_train_reg, y_train_reg)
Out[ ]:
KNeighborsRegressor(leaf_size=40, n_neighbors=2000, weights='distance')
In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook.
On GitHub, the HTML representation is unable to render, please try loading this page with nbviewer.org.
KNeighborsRegressor(leaf_size=40, n_neighbors=2000, weights='distance')
In [ ]:
# generar una lista con todos los modelos de regresion
models = [dtrV1, rfRV1, rfRV2, knnRV1]

i=1
# for que recorra la lista de modelos y que imprima el RMSE, R2 de cada modelo
for model in models:
    y_pred_reg = model.predict(X_test_reg)
    print(f'{i}° Modelo de Clasificación -> {model}\n')
    print('-'*100)
    print(
        f'El MSE del modelo es {mean_squared_error(y_test_reg, y_pred_reg):.3f}')
    print(
        f'El RMSE del modelo es $ {np.sqrt(mean_squared_error(y_test_reg, y_pred_reg)):.3f}')
    print(f'El R² del modelo es {r2_score(y_test_reg, y_pred_reg):.2f}\n')
    print('-'*100,'\n')
    i = i + 1
1° Modelo de Clasificación -> DecisionTreeRegressor(min_samples_leaf=5, min_samples_split=5, random_state=42)

----------------------------------------------------------------------------------------------------
El MSE del modelo es 0.161
El RMSE del modelo es $ 0.401
El R² del modelo es 0.36

---------------------------------------------------------------------------------------------------- 

2° Modelo de Clasificación -> RandomForestRegressor(max_depth=40, max_samples=0.8, min_samples_leaf=5,
                      min_samples_split=5, n_estimators=3, random_state=42)

----------------------------------------------------------------------------------------------------
El MSE del modelo es 0.128
El RMSE del modelo es $ 0.358
El R² del modelo es 0.49

---------------------------------------------------------------------------------------------------- 

3° Modelo de Clasificación -> RandomForestRegressor(max_depth=40, max_samples=0.8, min_samples_leaf=20,
                      min_samples_split=20, n_estimators=12, random_state=42)

----------------------------------------------------------------------------------------------------
El MSE del modelo es 0.114
El RMSE del modelo es $ 0.337
El R² del modelo es 0.55

---------------------------------------------------------------------------------------------------- 

4° Modelo de Clasificación -> KNeighborsRegressor(leaf_size=40, n_neighbors=2000, weights='distance')

----------------------------------------------------------------------------------------------------
El MSE del modelo es 0.230
El RMSE del modelo es $ 0.480
El R² del modelo es 0.08

---------------------------------------------------------------------------------------------------- 

Decisión¶

Los tres mejores modelos fueron los siguientes:

  • RandomForestRegressor() R²: 0.58 RandomForestRegressor ofrece el mejor rendimiento con un R² de 0.58. Su capacidad para manejar características no lineales y alta dimensionalidad lo hace ideal para datos complejos como los meteorológicos. Además, su naturaleza de ensemble ayuda a reducir el sobreajuste.

  • RandomForestRegressor(max_depth=40, max_samples=0.8, min_samples_leaf=20, min_samples_split=20, n_estimators=12, random_state=42) R²: 0.52 Este modelo optimizado de RandomForestRegressor, aunque ligeramente inferior al anterior, sigue siendo robusto. Las especificaciones de profundidad máxima y tamaño de muestra ayudan a controlar el sobreajuste, proporcionando un buen equilibrio entre sesgo y varianza.

  • GradientBoostingRegressor(n_estimators=500, random_state=42, tol=2) R²: 0.53 GradientBoostingRegressor con n_estimators ajustado a 500 ofrece un rendimiento cercano al mejor modelo de RandomForest. Su enfoque de boosting mejora iterativamente la precisión.

Teniendo en cuenta estos resultados el elegido será random fores sin hiper parametros

Clasificación¶

Target seleccionado : RainTomorrow_Yes¶

Para nuestra predicción hemos definido la variable objecto RainTomorrow_Yes, para ello nos apoyaremos en las siguientes variables

In [ ]:
df_clas = df_resampled[['RainTomorrow_Yes','RainToday_Yes','Humidity3pm','Humidity9am','RISK_MM','Cloud3pm','Sunshine','Cloud9am','Temp3pm','MaxTemp','Rainfall','Evaporation','Pressure3pm','Pressure9am',"Location_Sabana","Location_arido_calido","Location_mediterraneo","Location_semiarido_calido","Location_tropical_humedo", 'Date']]
corr = df_clas.corr()
sns.heatmap(corr, annot=True, linewidths=.9)
Out[ ]:
<Axes: >
No description has been provided for this image

Importe de librerías

In [ ]:
# importar todos los modelos de clasificacion de sklearn
from sklearn.tree import DecisionTreeClassifier
from sklearn.ensemble import RandomForestClassifier
from sklearn.ensemble import GradientBoostingClassifier
from sklearn.neighbors import KNeighborsClassifier

Separamos datos de entrenamiento y testeo¶

In [ ]:
# separar train y test de def_clas con un 80% para train y 20% para test y random_state=42
X_train_clas, X_test_clas, y_train_clas, y_test_clas = train_test_split(
    df_clas.drop(['RainTomorrow_Yes'], axis=1), df_clas['RainTomorrow_Yes'], test_size=0.2, random_state=42)

Modelos sin hiperparámetros¶

Realizaremos un entrenamiento previo sin hiperparámetros para tener una vista preliminar del posible mejor modelo, los modelos seleccionados serán:

  • DecisionTreeClassifier
  • RandomForestClassifier
  • GradientBoostingClassifier
  • KNeighborsClassifier
In [ ]:
dt = DecisionTreeClassifier()
dt.fit(X_train_clas, y_train_clas)
Out[ ]:
DecisionTreeClassifier()
In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook.
On GitHub, the HTML representation is unable to render, please try loading this page with nbviewer.org.
DecisionTreeClassifier()
In [ ]:
rf = RandomForestClassifier()
rf.fit(X_train_clas, y_train_clas)
Out[ ]:
RandomForestClassifier()
In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook.
On GitHub, the HTML representation is unable to render, please try loading this page with nbviewer.org.
RandomForestClassifier()
In [ ]:
gb = GradientBoostingClassifier()
gb.fit(X_train_clas, y_train_clas)
Out[ ]:
GradientBoostingClassifier()
In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook.
On GitHub, the HTML representation is unable to render, please try loading this page with nbviewer.org.
GradientBoostingClassifier()
In [ ]:
knn = KNeighborsClassifier()
knn.fit(X_train_clas, y_train_clas)
Out[ ]:
KNeighborsClassifier()
In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook.
On GitHub, the HTML representation is unable to render, please try loading this page with nbviewer.org.
KNeighborsClassifier()

Entrenamiento de Modelos con hiperparámetros¶

DecisionTreeClassifier¶

DecisionTreeClassifier V1¶
In [ ]:
dt_1 = DecisionTreeClassifier(max_depth=2, random_state=42, criterion='entropy')
dt_1.fit(X_train_clas, y_train_clas)
Out[ ]:
DecisionTreeClassifier(criterion='entropy', max_depth=2, random_state=42)
In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook.
On GitHub, the HTML representation is unable to render, please try loading this page with nbviewer.org.
DecisionTreeClassifier(criterion='entropy', max_depth=2, random_state=42)
DecisionTreeClassifier V2¶
In [ ]:
dt_2 = DecisionTreeClassifier(
    max_depth=2, random_state=42, criterion='gini')
dt_2.fit(X_train_clas, y_train_clas)
Out[ ]:
DecisionTreeClassifier(max_depth=2, random_state=42)
In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook.
On GitHub, the HTML representation is unable to render, please try loading this page with nbviewer.org.
DecisionTreeClassifier(max_depth=2, random_state=42)
DecisionTreeClassifier V3¶
In [ ]:
dt_3 = DecisionTreeClassifier(
    max_depth=2, random_state=42, criterion='log_loss')
dt_3.fit(X_train_clas, y_train_clas)
Out[ ]:
DecisionTreeClassifier(criterion='log_loss', max_depth=2, random_state=42)
In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook.
On GitHub, the HTML representation is unable to render, please try loading this page with nbviewer.org.
DecisionTreeClassifier(criterion='log_loss', max_depth=2, random_state=42)
DecisionTreeClassifier V4¶
In [ ]:
dt_4 = DecisionTreeClassifier(
    max_depth=2, random_state=42, criterion='gini', min_samples_leaf=10)
dt_4.fit(X_train_clas, y_train_clas)
Out[ ]:
DecisionTreeClassifier(max_depth=2, min_samples_leaf=10, random_state=42)
In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook.
On GitHub, the HTML representation is unable to render, please try loading this page with nbviewer.org.
DecisionTreeClassifier(max_depth=2, min_samples_leaf=10, random_state=42)

RandomForestClassifier¶

RandomForestClassifier V1¶
In [ ]:
rf_1 = RandomForestClassifier(max_depth=2, random_state=42)
rf_1.fit(X_train_clas, y_train_clas)
Out[ ]:
RandomForestClassifier(max_depth=2, random_state=42)
In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook.
On GitHub, the HTML representation is unable to render, please try loading this page with nbviewer.org.
RandomForestClassifier(max_depth=2, random_state=42)
RandomForestClassifier V2¶
In [ ]:
rf_2 = RandomForestClassifier(max_depth=3, random_state=42)
rf_2.fit(X_train_clas, y_train_clas)
Out[ ]:
RandomForestClassifier(max_depth=3, random_state=42)
In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook.
On GitHub, the HTML representation is unable to render, please try loading this page with nbviewer.org.
RandomForestClassifier(max_depth=3, random_state=42)
RandomForestClassifier V3¶
In [ ]:
rf_3 = RandomForestClassifier(max_depth=15, random_state=42)
rf_3.fit(X_train_clas, y_train_clas)
Out[ ]:
RandomForestClassifier(max_depth=15, random_state=42)
In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook.
On GitHub, the HTML representation is unable to render, please try loading this page with nbviewer.org.
RandomForestClassifier(max_depth=15, random_state=42)
RandomForestClassifier V4¶
In [ ]:
rf_4 = RandomForestClassifier(max_depth=3, random_state=42,
                              min_samples_leaf=10, n_estimators=1000)
rf_4.fit(X_train_clas, y_train_clas)
Out[ ]:
RandomForestClassifier(max_depth=3, min_samples_leaf=10, n_estimators=1000,
                       random_state=42)
In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook.
On GitHub, the HTML representation is unable to render, please try loading this page with nbviewer.org.
RandomForestClassifier(max_depth=3, min_samples_leaf=10, n_estimators=1000,
                       random_state=42)
RandomForestClassifier V5¶
In [ ]:
rf_5 = RandomForestClassifier(max_depth=3, random_state=42,
                              min_samples_leaf=10, n_estimators=1000, max_features='sqrt')
rf_5.fit(X_train_clas, y_train_clas)
Out[ ]:
RandomForestClassifier(max_depth=3, min_samples_leaf=10, n_estimators=1000,
                       random_state=42)
In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook.
On GitHub, the HTML representation is unable to render, please try loading this page with nbviewer.org.
RandomForestClassifier(max_depth=3, min_samples_leaf=10, n_estimators=1000,
                       random_state=42)
RandomForestClassifier V6¶
In [ ]:
rf_6 = RandomForestClassifier(max_depth=3, random_state=42, min_samples_leaf=10,
                              n_estimators=1000, max_features='log2', max_samples=0.8)
rf_6.fit(X_train_clas, y_train_clas)
Out[ ]:
RandomForestClassifier(max_depth=3, max_features='log2', max_samples=0.8,
                       min_samples_leaf=10, n_estimators=1000, random_state=42)
In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook.
On GitHub, the HTML representation is unable to render, please try loading this page with nbviewer.org.
RandomForestClassifier(max_depth=3, max_features='log2', max_samples=0.8,
                       min_samples_leaf=10, n_estimators=1000, random_state=42)

GradientBoostingClassifier¶

GradientBoostingClassifier V1¶
In [ ]:
gb_1 = GradientBoostingClassifier(max_depth=2, random_state=42)
gb_1.fit(X_train_clas, y_train_clas)
Out[ ]:
GradientBoostingClassifier(max_depth=2, random_state=42)
In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook.
On GitHub, the HTML representation is unable to render, please try loading this page with nbviewer.org.
GradientBoostingClassifier(max_depth=2, random_state=42)
GradientBoostingClassifier V2¶
In [ ]:
gb_2 = GradientBoostingClassifier(loss='exponential' ,learning_rate=0.1, n_estimators=150, max_depth=3, random_state=42)
gb_2.fit(X_train_clas, y_train_clas)
Out[ ]:
GradientBoostingClassifier(loss='exponential', n_estimators=150,
                           random_state=42)
In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook.
On GitHub, the HTML representation is unable to render, please try loading this page with nbviewer.org.
GradientBoostingClassifier(loss='exponential', n_estimators=150,
                           random_state=42)
GradientBoostingClassifier V3¶
In [ ]:
gb_3 = GradientBoostingClassifier(
    learning_rate=0.001, n_estimators=1500, max_depth=3, random_state=42, min_samples_leaf=10)
gb_3.fit(X_train_clas, y_train_clas)
Out[ ]:
GradientBoostingClassifier(learning_rate=0.001, min_samples_leaf=10,
                           n_estimators=1500, random_state=42)
In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook.
On GitHub, the HTML representation is unable to render, please try loading this page with nbviewer.org.
GradientBoostingClassifier(learning_rate=0.001, min_samples_leaf=10,
                           n_estimators=1500, random_state=42)

KNeighborsClassifier¶

KNeighborsClassifier V1¶
In [ ]:
knn_1 = KNeighborsClassifier(n_neighbors=2)
knn_1.fit(X_train_clas, y_train_clas)
Out[ ]:
KNeighborsClassifier(n_neighbors=2)
In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook.
On GitHub, the HTML representation is unable to render, please try loading this page with nbviewer.org.
KNeighborsClassifier(n_neighbors=2)

Se genera una lista con los modelos

In [ ]:
models = [  dt, rf, gb, knn, 
            dt_1, dt_2, dt_3, dt_4, 
            rf_1, rf_2, rf_3, rf_4, rf_5, rf_6,
            gb_1, gb_2, gb_3,
            knn_1]

Vista del Matriz de confusión y suma de aciertos¶

In [ ]:
# matriz de confusion para cada modelo de clasificacion
from sklearn.metrics import confusion_matrix, classification_report
i=1
for model in models:

    y_pred_clas = model.predict(X_test_clas)
    cm = confusion_matrix(y_test_clas, y_pred_clas)
    print(f'{i}° Modelo de Clasificación -> {model}\n')
    # grafico de matriz de confusion con la diagonal en un color distinto
    plt.figure(figsize=(3, 3))
    sns.heatmap(cm, annot=True, fmt='g', cmap='Blues')
    plt.xlabel('Predicted')
    plt.ylabel('True')
    plt.title('Matriz de Confusión del Modelo')
    plt.show()
    
    print(
        f'Suma de la diagonal de la matriz de confusión del modelo es: {cm.trace()}\n')
    print('-'*100,'\n')

    i += 1
1° Modelo de Clasificación -> DecisionTreeClassifier()

No description has been provided for this image
Suma de la diagonal de la matriz de confusión del modelo es: 35090

---------------------------------------------------------------------------------------------------- 

2° Modelo de Clasificación -> RandomForestClassifier()

No description has been provided for this image
Suma de la diagonal de la matriz de confusión del modelo es: 38149

---------------------------------------------------------------------------------------------------- 

3° Modelo de Clasificación -> GradientBoostingClassifier()

No description has been provided for this image
Suma de la diagonal de la matriz de confusión del modelo es: 36070

---------------------------------------------------------------------------------------------------- 

4° Modelo de Clasificación -> KNeighborsClassifier()

No description has been provided for this image
Suma de la diagonal de la matriz de confusión del modelo es: 32181

---------------------------------------------------------------------------------------------------- 

5° Modelo de Clasificación -> DecisionTreeClassifier(criterion='entropy', max_depth=2, random_state=42)

No description has been provided for this image
Suma de la diagonal de la matriz de confusión del modelo es: 31588

---------------------------------------------------------------------------------------------------- 

6° Modelo de Clasificación -> DecisionTreeClassifier(max_depth=2, random_state=42)

No description has been provided for this image
Suma de la diagonal de la matriz de confusión del modelo es: 31588

---------------------------------------------------------------------------------------------------- 

7° Modelo de Clasificación -> DecisionTreeClassifier(criterion='log_loss', max_depth=2, random_state=42)

No description has been provided for this image
Suma de la diagonal de la matriz de confusión del modelo es: 31588

---------------------------------------------------------------------------------------------------- 

8° Modelo de Clasificación -> DecisionTreeClassifier(max_depth=2, min_samples_leaf=10, random_state=42)

No description has been provided for this image
Suma de la diagonal de la matriz de confusión del modelo es: 31588

---------------------------------------------------------------------------------------------------- 

9° Modelo de Clasificación -> RandomForestClassifier(max_depth=2, random_state=42)

No description has been provided for this image
Suma de la diagonal de la matriz de confusión del modelo es: 31847

---------------------------------------------------------------------------------------------------- 

10° Modelo de Clasificación -> RandomForestClassifier(max_depth=3, random_state=42)

No description has been provided for this image
Suma de la diagonal de la matriz de confusión del modelo es: 32098

---------------------------------------------------------------------------------------------------- 

11° Modelo de Clasificación -> RandomForestClassifier(max_depth=15, random_state=42)

No description has been provided for this image
Suma de la diagonal de la matriz de confusión del modelo es: 36208

---------------------------------------------------------------------------------------------------- 

12° Modelo de Clasificación -> RandomForestClassifier(max_depth=3, min_samples_leaf=10, n_estimators=1000,
                       random_state=42)

No description has been provided for this image
Suma de la diagonal de la matriz de confusión del modelo es: 32193

---------------------------------------------------------------------------------------------------- 

13° Modelo de Clasificación -> RandomForestClassifier(max_depth=3, min_samples_leaf=10, n_estimators=1000,
                       random_state=42)

No description has been provided for this image
Suma de la diagonal de la matriz de confusión del modelo es: 32193

---------------------------------------------------------------------------------------------------- 

14° Modelo de Clasificación -> RandomForestClassifier(max_depth=3, max_features='log2', max_samples=0.8,
                       min_samples_leaf=10, n_estimators=1000, random_state=42)

No description has been provided for this image
Suma de la diagonal de la matriz de confusión del modelo es: 32196

---------------------------------------------------------------------------------------------------- 

15° Modelo de Clasificación -> GradientBoostingClassifier(max_depth=2, random_state=42)

No description has been provided for this image
Suma de la diagonal de la matriz de confusión del modelo es: 34764

---------------------------------------------------------------------------------------------------- 

16° Modelo de Clasificación -> GradientBoostingClassifier(loss='exponential', n_estimators=150,
                           random_state=42)

No description has been provided for this image
Suma de la diagonal de la matriz de confusión del modelo es: 36785

---------------------------------------------------------------------------------------------------- 

17° Modelo de Clasificación -> GradientBoostingClassifier(learning_rate=0.001, min_samples_leaf=10,
                           n_estimators=1500, random_state=42)

No description has been provided for this image
Suma de la diagonal de la matriz de confusión del modelo es: 33261

---------------------------------------------------------------------------------------------------- 

18° Modelo de Clasificación -> KNeighborsClassifier(n_neighbors=2)

No description has been provided for this image
Suma de la diagonal de la matriz de confusión del modelo es: 32702

---------------------------------------------------------------------------------------------------- 

Analisis de accuracy, sensibilidad, precisión y F1¶

In [ ]:
# for que recorra la lista de modelos y que imprima el accuracy, precision, recall, f1-score de cada modelo

from sklearn.metrics import accuracy_score, precision_score, recall_score, f1_score
i = 1
for model in models:
    y_pred_clas = model.predict(X_test_clas)
    print(f'{i}° Modelo de Clasificación -> {model}\n')
    print('-'*100)
    print(f'El accuracy del modelo es {accuracy_score(y_test_clas, y_pred_clas):.2f}')
    print(f'El precision del modelo es {precision_score(y_test_clas, y_pred_clas):.2f}')
    print(f'El recall del modelo es {recall_score(y_test_clas, y_pred_clas):.2f}')
    print(f'El f1-score del modelo es {f1_score(y_test_clas, y_pred_clas):.2f}\n')
    print('-'*100,'\n')
    i += 1

    
1° Modelo de Clasificación -> DecisionTreeClassifier()

----------------------------------------------------------------------------------------------------
El accuracy del modelo es 0.80
El precision del modelo es 0.79
El recall del modelo es 0.80
El f1-score del modelo es 0.80

---------------------------------------------------------------------------------------------------- 

2° Modelo de Clasificación -> RandomForestClassifier()

----------------------------------------------------------------------------------------------------
El accuracy del modelo es 0.86
El precision del modelo es 0.90
El recall del modelo es 0.82
El f1-score del modelo es 0.86

---------------------------------------------------------------------------------------------------- 

3° Modelo de Clasificación -> GradientBoostingClassifier()

----------------------------------------------------------------------------------------------------
El accuracy del modelo es 0.82
El precision del modelo es 0.85
El recall del modelo es 0.77
El f1-score del modelo es 0.81

---------------------------------------------------------------------------------------------------- 

4° Modelo de Clasificación -> KNeighborsClassifier()

----------------------------------------------------------------------------------------------------
El accuracy del modelo es 0.73
El precision del modelo es 0.71
El recall del modelo es 0.78
El f1-score del modelo es 0.74

---------------------------------------------------------------------------------------------------- 

5° Modelo de Clasificación -> DecisionTreeClassifier(criterion='entropy', max_depth=2, random_state=42)

----------------------------------------------------------------------------------------------------
El accuracy del modelo es 0.72
El precision del modelo es 0.70
El recall del modelo es 0.77
El f1-score del modelo es 0.73

---------------------------------------------------------------------------------------------------- 

6° Modelo de Clasificación -> DecisionTreeClassifier(max_depth=2, random_state=42)

----------------------------------------------------------------------------------------------------
El accuracy del modelo es 0.72
El precision del modelo es 0.70
El recall del modelo es 0.77
El f1-score del modelo es 0.73

---------------------------------------------------------------------------------------------------- 

7° Modelo de Clasificación -> DecisionTreeClassifier(criterion='log_loss', max_depth=2, random_state=42)

----------------------------------------------------------------------------------------------------
El accuracy del modelo es 0.72
El precision del modelo es 0.70
El recall del modelo es 0.77
El f1-score del modelo es 0.73

---------------------------------------------------------------------------------------------------- 

8° Modelo de Clasificación -> DecisionTreeClassifier(max_depth=2, min_samples_leaf=10, random_state=42)

----------------------------------------------------------------------------------------------------
El accuracy del modelo es 0.72
El precision del modelo es 0.70
El recall del modelo es 0.77
El f1-score del modelo es 0.73

---------------------------------------------------------------------------------------------------- 

9° Modelo de Clasificación -> RandomForestClassifier(max_depth=2, random_state=42)

----------------------------------------------------------------------------------------------------
El accuracy del modelo es 0.72
El precision del modelo es 0.74
El recall del modelo es 0.68
El f1-score del modelo es 0.71

---------------------------------------------------------------------------------------------------- 

10° Modelo de Clasificación -> RandomForestClassifier(max_depth=3, random_state=42)

----------------------------------------------------------------------------------------------------
El accuracy del modelo es 0.73
El precision del modelo es 0.74
El recall del modelo es 0.70
El f1-score del modelo es 0.72

---------------------------------------------------------------------------------------------------- 

11° Modelo de Clasificación -> RandomForestClassifier(max_depth=15, random_state=42)

----------------------------------------------------------------------------------------------------
El accuracy del modelo es 0.82
El precision del modelo es 0.86
El recall del modelo es 0.77
El f1-score del modelo es 0.81

---------------------------------------------------------------------------------------------------- 

12° Modelo de Clasificación -> RandomForestClassifier(max_depth=3, min_samples_leaf=10, n_estimators=1000,
                       random_state=42)

----------------------------------------------------------------------------------------------------
El accuracy del modelo es 0.73
El precision del modelo es 0.74
El recall del modelo es 0.71
El f1-score del modelo es 0.72

---------------------------------------------------------------------------------------------------- 

13° Modelo de Clasificación -> RandomForestClassifier(max_depth=3, min_samples_leaf=10, n_estimators=1000,
                       random_state=42)

----------------------------------------------------------------------------------------------------
El accuracy del modelo es 0.73
El precision del modelo es 0.74
El recall del modelo es 0.71
El f1-score del modelo es 0.72

---------------------------------------------------------------------------------------------------- 

14° Modelo de Clasificación -> RandomForestClassifier(max_depth=3, max_features='log2', max_samples=0.8,
                       min_samples_leaf=10, n_estimators=1000, random_state=42)

----------------------------------------------------------------------------------------------------
El accuracy del modelo es 0.73
El precision del modelo es 0.74
El recall del modelo es 0.71
El f1-score del modelo es 0.72

---------------------------------------------------------------------------------------------------- 

15° Modelo de Clasificación -> GradientBoostingClassifier(max_depth=2, random_state=42)

----------------------------------------------------------------------------------------------------
El accuracy del modelo es 0.79
El precision del modelo es 0.81
El recall del modelo es 0.75
El f1-score del modelo es 0.78

---------------------------------------------------------------------------------------------------- 

16° Modelo de Clasificación -> GradientBoostingClassifier(loss='exponential', n_estimators=150,
                           random_state=42)

----------------------------------------------------------------------------------------------------
El accuracy del modelo es 0.83
El precision del modelo es 0.87
El recall del modelo es 0.78
El f1-score del modelo es 0.83

---------------------------------------------------------------------------------------------------- 

17° Modelo de Clasificación -> GradientBoostingClassifier(learning_rate=0.001, min_samples_leaf=10,
                           n_estimators=1500, random_state=42)

----------------------------------------------------------------------------------------------------
El accuracy del modelo es 0.75
El precision del modelo es 0.81
El recall del modelo es 0.66
El f1-score del modelo es 0.73

---------------------------------------------------------------------------------------------------- 

18° Modelo de Clasificación -> KNeighborsClassifier(n_neighbors=2)

----------------------------------------------------------------------------------------------------
El accuracy del modelo es 0.74
El precision del modelo es 0.79
El recall del modelo es 0.66
El f1-score del modelo es 0.72

---------------------------------------------------------------------------------------------------- 

Gráficos de la curva curva ROC/AUC¶

In [ ]:
import  matplotlib.pyplot as plt
from sklearn import metrics
from sklearn.metrics import roc_curve, auc
def plot_roc_chart(model, X_test, y_test):
    # calculate the fpr and tpr for all thresholds of the classification
    probs = model.predict_proba(X_test)
    preds = probs[:, 1]
    fpr, tpr, threshold = metrics.roc_curve(y_test, preds)
    roc_auc = metrics.auc(fpr, tpr)

    # method I: plt
    plt.figure(figsize=(3, 3))
    plt.title('Receiver Operating Characteristic')
    plt.plot(fpr, tpr, 'b', label='AUC = %0.2f' % roc_auc)
    plt.legend(loc='lower right')
    plt.plot([0, 1], [0, 1], 'r--')
    plt.xlim([0, 1])
    plt.ylim([0, 1])
    plt.ylabel('True Positive Rate')
    plt.xlabel('False Positive Rate')
    plt.show()
    return probs

Gráfico y comparación¶

In [ ]:
# trazar la curva ROC/AUC para cada modelo de clasificacion comparando con las clasificaciones

from sklearn.metrics import roc_curve, auc
i = 1
for model in models:
    y_pred_clas = model.predict(X_test_clas)
    fpr, tpr, thresholds = roc_curve(y_test_clas, y_pred_clas)
    roc_auc = auc(fpr, tpr)
    accuaracy = accuracy_score(y_test_clas, y_pred_clas)
    dif = roc_auc - accuaracy
    print(f'{i}° Modelo de Clasificación -> {model}\n')
    print('-'*100)
    print(
        f'El área bajo la curva ROC del modelo es {roc_auc:.2f} vs {accuaracy:.2f} de accuracy')
    print(f'generando una diferencia de {dif:.2f}\n')
    plot_roc_chart(model, X_test_clas, y_test_clas)
    print('-'*100,'\n')
    i += 1
1° Modelo de Clasificación -> DecisionTreeClassifier()

----------------------------------------------------------------------------------------------------
El área bajo la curva ROC del modelo es 0.80 vs 0.80 de accuracy
generando una diferencia de -0.00

No description has been provided for this image
---------------------------------------------------------------------------------------------------- 

2° Modelo de Clasificación -> RandomForestClassifier()

----------------------------------------------------------------------------------------------------
El área bajo la curva ROC del modelo es 0.86 vs 0.86 de accuracy
generando una diferencia de 0.00

No description has been provided for this image
---------------------------------------------------------------------------------------------------- 

3° Modelo de Clasificación -> GradientBoostingClassifier()

----------------------------------------------------------------------------------------------------
El área bajo la curva ROC del modelo es 0.82 vs 0.82 de accuracy
generando una diferencia de 0.00

No description has been provided for this image
---------------------------------------------------------------------------------------------------- 

4° Modelo de Clasificación -> KNeighborsClassifier()

----------------------------------------------------------------------------------------------------
El área bajo la curva ROC del modelo es 0.73 vs 0.73 de accuracy
generando una diferencia de -0.00

No description has been provided for this image
---------------------------------------------------------------------------------------------------- 

5° Modelo de Clasificación -> DecisionTreeClassifier(criterion='entropy', max_depth=2, random_state=42)

----------------------------------------------------------------------------------------------------
El área bajo la curva ROC del modelo es 0.72 vs 0.72 de accuracy
generando una diferencia de -0.00

No description has been provided for this image
---------------------------------------------------------------------------------------------------- 

6° Modelo de Clasificación -> DecisionTreeClassifier(max_depth=2, random_state=42)

----------------------------------------------------------------------------------------------------
El área bajo la curva ROC del modelo es 0.72 vs 0.72 de accuracy
generando una diferencia de -0.00

No description has been provided for this image
---------------------------------------------------------------------------------------------------- 

7° Modelo de Clasificación -> DecisionTreeClassifier(criterion='log_loss', max_depth=2, random_state=42)

----------------------------------------------------------------------------------------------------
El área bajo la curva ROC del modelo es 0.72 vs 0.72 de accuracy
generando una diferencia de -0.00

No description has been provided for this image
---------------------------------------------------------------------------------------------------- 

8° Modelo de Clasificación -> DecisionTreeClassifier(max_depth=2, min_samples_leaf=10, random_state=42)

----------------------------------------------------------------------------------------------------
El área bajo la curva ROC del modelo es 0.72 vs 0.72 de accuracy
generando una diferencia de -0.00

No description has been provided for this image
---------------------------------------------------------------------------------------------------- 

9° Modelo de Clasificación -> RandomForestClassifier(max_depth=2, random_state=42)

----------------------------------------------------------------------------------------------------
El área bajo la curva ROC del modelo es 0.72 vs 0.72 de accuracy
generando una diferencia de 0.00

No description has been provided for this image
---------------------------------------------------------------------------------------------------- 

10° Modelo de Clasificación -> RandomForestClassifier(max_depth=3, random_state=42)

----------------------------------------------------------------------------------------------------
El área bajo la curva ROC del modelo es 0.73 vs 0.73 de accuracy
generando una diferencia de 0.00

No description has been provided for this image
---------------------------------------------------------------------------------------------------- 

11° Modelo de Clasificación -> RandomForestClassifier(max_depth=15, random_state=42)

----------------------------------------------------------------------------------------------------
El área bajo la curva ROC del modelo es 0.82 vs 0.82 de accuracy
generando una diferencia de 0.00

No description has been provided for this image
---------------------------------------------------------------------------------------------------- 

12° Modelo de Clasificación -> RandomForestClassifier(max_depth=3, min_samples_leaf=10, n_estimators=1000,
                       random_state=42)

----------------------------------------------------------------------------------------------------
El área bajo la curva ROC del modelo es 0.73 vs 0.73 de accuracy
generando una diferencia de 0.00

No description has been provided for this image
---------------------------------------------------------------------------------------------------- 

13° Modelo de Clasificación -> RandomForestClassifier(max_depth=3, min_samples_leaf=10, n_estimators=1000,
                       random_state=42)

----------------------------------------------------------------------------------------------------
El área bajo la curva ROC del modelo es 0.73 vs 0.73 de accuracy
generando una diferencia de 0.00

No description has been provided for this image
---------------------------------------------------------------------------------------------------- 

14° Modelo de Clasificación -> RandomForestClassifier(max_depth=3, max_features='log2', max_samples=0.8,
                       min_samples_leaf=10, n_estimators=1000, random_state=42)

----------------------------------------------------------------------------------------------------
El área bajo la curva ROC del modelo es 0.73 vs 0.73 de accuracy
generando una diferencia de 0.00

No description has been provided for this image
---------------------------------------------------------------------------------------------------- 

15° Modelo de Clasificación -> GradientBoostingClassifier(max_depth=2, random_state=42)

----------------------------------------------------------------------------------------------------
El área bajo la curva ROC del modelo es 0.79 vs 0.79 de accuracy
generando una diferencia de 0.00

No description has been provided for this image
---------------------------------------------------------------------------------------------------- 

16° Modelo de Clasificación -> GradientBoostingClassifier(loss='exponential', n_estimators=150,
                           random_state=42)

----------------------------------------------------------------------------------------------------
El área bajo la curva ROC del modelo es 0.83 vs 0.83 de accuracy
generando una diferencia de 0.00

No description has been provided for this image
---------------------------------------------------------------------------------------------------- 

17° Modelo de Clasificación -> GradientBoostingClassifier(learning_rate=0.001, min_samples_leaf=10,
                           n_estimators=1500, random_state=42)

----------------------------------------------------------------------------------------------------
El área bajo la curva ROC del modelo es 0.75 vs 0.75 de accuracy
generando una diferencia de 0.00

No description has been provided for this image
---------------------------------------------------------------------------------------------------- 

18° Modelo de Clasificación -> KNeighborsClassifier(n_neighbors=2)

----------------------------------------------------------------------------------------------------
El área bajo la curva ROC del modelo es 0.74 vs 0.74 de accuracy
generando una diferencia de 0.00

No description has been provided for this image
---------------------------------------------------------------------------------------------------- 

Características más importantes¶

In [ ]:
## Identifica las características más importantes del dataset usando RandomForest

for score, name in zip(rf_1.feature_importances_, X_train_clas.columns):
    print(f'La característica {name} tiene un score de {score:.2f}')
La característica RainToday_Yes tiene un score de 0.39
La característica Humidity3pm tiene un score de 0.06
La característica Humidity9am tiene un score de 0.02
La característica RISK_MM tiene un score de 0.16
La característica Cloud3pm tiene un score de 0.04
La característica Sunshine tiene un score de 0.05
La característica Cloud9am tiene un score de 0.06
La característica Temp3pm tiene un score de 0.00
La característica MaxTemp tiene un score de 0.00
La característica Rainfall tiene un score de 0.15
La característica Evaporation tiene un score de 0.01
La característica Pressure3pm tiene un score de 0.00
La característica Pressure9am tiene un score de 0.00
La característica Location_Sabana tiene un score de 0.00
La característica Location_arido_calido tiene un score de 0.03
La característica Location_mediterraneo tiene un score de 0.01
La característica Location_semiarido_calido tiene un score de 0.02
La característica Location_tropical_humedo tiene un score de 0.00
La característica Date tiene un score de 0.00

Decisión¶

El algoritmo utilizado,será el modelo N° 9 RandomForestClassifier sin hiperparámetros ya que es el que mejor predice los Verdaderos negativos con 5.545, dando asi un recall de 81%, y también es el que nos da el mayor accuracy con un 0.85%

RandomForestClassifier() Accuracy: 0.85 Precision: 0.89 Recall: 0.81 F1-Score: 0.85 Este modelo presenta el mejor rendimiento general con los valores más altos de precisión y F1-score

Modelos no supervisado¶

Casos de uso para aprendizaje no supervisado¶

Para esto usaremos las columnas 'RainToday_Yes','Rainfall','Sunshine','Humidity3pm','Cloud3pm','Cloud9am','RainTomorrow_Yes','Humidity9am','WindGustSpeed','Pressure9am','Pressure3pm','MinTemp','WindSpeed9am','Temp9am','Temp3pm'

  1. Clasificación para saber si llovera mañana:
  • Cluster 1: No
  • Cluster 2: Si
  1. Clasificación por Tipo de clima:
  • Cluster 1: Clima Tropical.
  • Cluster 2: Clima Desértico.
  • Cluster 3: Clima Mediterráneo.
  • Cluster 4: Clima Oceánico.

Clusterización¶

Ya que nuestro caso de uso elegido es el Clasificación por Tipo de Cliente, tenemos como hipótesis usar aproximadamente 4-6 clusters usaremos un rango de 2 a 11, para cumplir con los 10 k's distintos solicitados

In [ ]:
from sklearn.cluster import MiniBatchKMeans
from sklearn.metrics import silhouette_score

# Rango de clusters a probar
k_range = np.arange(2, 6)

# crear un df_clustering usando el df con las columnas
df_clustering_complete = df[['RainToday_Yes','Humidity3pm','Cloud3pm','Sunshine','Temp3pm','Rainfall','Pressure3pm',"Location_Sabana","Location_arido_calido","Location_mediterraneo","Location_semiarido_calido","Location_tropical_humedo", 'Date']]

# Normalizar el df_clustering
from sklearn.preprocessing import StandardScaler
scaler = StandardScaler()
df_clustering = scaler.fit_transform(df_clustering_complete)


# Reducir la dimensionalidad del df_clustering a 2 dimensiones usando PCA
from sklearn.decomposition import PCA
pca = PCA(n_components=2)
df_clustering = pca.fit_transform(df_clustering)





# realizar el clustering con MiniBatchKMeans
inertia = []
silhouette = []
for k in k_range:
    mbk = MiniBatchKMeans(n_clusters=k, batch_size=1000, random_state=42, n_init=10)
    mbk.fit(df_clustering)
    inertia.append(mbk.inertia_)
    silhouette.append(silhouette_score(df_clustering, mbk.labels_))
    # graficar la clusterizacion con el valor de k y el valor de rand separando los clusters por colores y mostrando el centroide de cada cluster, separando las clusters por colores y con lineas
    plt.figure(figsize=(10, 5))
    plt.scatter(df_clustering[:, 0], df_clustering[:, 1], c=mbk.labels_, cmap='rainbow')
    plt.scatter(mbk.cluster_centers_[:, 0], mbk.cluster_centers_[:, 1], marker='*', s=200, c='#050505')
    plt.title(f'Clustering con {k} clusters')
    plt.show()
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
In [ ]:
# relizar el metodo del codo para encontrar el numero de clusters optimo

plt.figure(figsize=(10, 5))
plt.plot(k_range, inertia, 'bx-')
plt.xlabel('k')
plt.ylabel('Inertia')
plt.title('Método del Codo')
plt.show()
No description has been provided for this image
In [ ]:
# Graficar la puntuación de la silueta para diferentes valores de k
plt.figure(figsize=(10, 5))
plt.plot(k_range, silhouette, marker='o', linestyle='-', color='b')
plt.title('Puntuación de la Silueta vs Número de Clusters')
plt.xlabel('Número de Clusters')
plt.ylabel('Puntuación de la Silueta')
plt.show()
No description has been provided for this image

Utilizando la gráfica para ver cual tiene menor inercia hemos decidido el numero k=3 como codo

Decisión de clasificación¶

Ya que el algoritmo dio 3 clusters cambiaremos la definición anterior a la siguiente:

  1. Clasificación por tipo de Clima: Un ejemplo de clusterización sería:
  • Cluster 1: Clima Tropical.
  • Cluster 2: Clima Desértico.
  • Cluster 3: Clima Mediterráneo.

Elección de regresión¶

Para determinar los mejores tres modelos de regresión seleccionaremos aquellos con el menor MSE y RMSE, y el mayor R², lo que indica un mejor rendimiento en términos de precisión y ajuste del modelo. Estos son los mejores tres modelos basados en estas métricas:

Modelo 2: RandomForestRegressor()
MSE: 0.100
RMSE: 0.316
R²: 0.60

Modelo 12: RandomForestRegressor(max_depth=40, max_samples=0.8, min_samples_leaf=20, min_samples_split=20, n_estimators=12, random_state=42)
MSE: 0.114
RMSE: 0.337
R²: 0.55

Modelo 6: GradientBoostingRegressor(n_estimators=500, random_state=42, tol=2)
MSE: 0.112
RMSE: 0.335
R²: 0.55

Según estos resultados el elegido será el Modelo 2: RandomForestRegressor(), lo cual no esperabamos al ser el modelo sin hiper parametros pero la vida nos da sorpresas todos los días.

Elección de clasificación¶

Por otra parte, aquí están los mejores tres modelos basados en el f1-score y teniendo en cuenta métricas como el accuracy, precision, recall y f1-score.:

Modelo 2: RandomForestClassifier()
Accuracy: 0.86
Precision: 0.90
Recall: 0.82
F1-Score: 0.86

Modelo 16: GradientBoostingClassifier(loss='exponential', n_estimators=150, random_state=42)
Accuracy: 0.83
Precision: 0.87
Recall: 0.78
F1-Score: 0.83

Modelo 3: GradientBoostingClassifier()
Accuracy: 0.82
Precision: 0.85
Recall: 0.77
F1-Score: 0.81

Estos modelos tienen los f1-scores más altos y, por lo tanto, son los mejores en términos de equilibrio entre precision y recall. Además, estos modelos también tienen altos valores de accuracy y precision, lo que sugiere un buen rendimiento general dando como elegido el Modelo 2: RandomForestClassifier(), siendo uno de los modelos probados sin hiper parámetros y logrando las mejores métricas.